]> git.tdb.fi Git - gldbg.git/blob - flavors/gl/source/glstate.cpp
Replace per-file license notices with License.txt
[gldbg.git] / flavors / gl / source / glstate.cpp
1 #include <stdexcept>
2 #include "glstate.h"
3
4 using namespace std;
5
6 namespace {
7
8 template<typename T>
9 float normalize(T v);
10
11 template<>
12 float normalize<GLubyte>(GLubyte v)
13 { return v/255.0f; }
14
15 template<>
16 float normalize<GLbyte>(GLbyte v)
17 { return (2*v+1)/255.0f; }
18
19 template<typename T, void (*func)(void *, float)>
20 void wrap_normalized(void *user_data, T v0)
21 { func(user_data, v0); }
22
23 template<typename T, void (*func)(void *, float, float)>
24 void wrap_normalized(void *user_data, T v0, T v1)
25 { func(user_data, v0, v1); }
26
27 template<typename T, void (*func)(void *, float, float, float)>
28 void wrap_normalized(void *user_data, T v0, T v1, T v2)
29 { func(user_data, v0, v1, v2); }
30
31 template<typename T, void (*func)(void *, float, float, float, float)>
32 void wrap_normalized(void *user_data, T v0, T v1, T v2, T v3)
33 { func(user_data, v0, v1, v2, v3); }
34
35 template<typename T, void (*func)(void *, T)>
36 void wrap_array(void *user_data, const T *v)
37 { func(user_data, v[0]); }
38
39 template<typename T, void (*func)(void *, T, T)>
40 void wrap_array(void *user_data, const T *v)
41 { func(user_data, v[0], v[1]); }
42
43 template<typename T, void (*func)(void *, T, T, T)>
44 void wrap_array(void *user_data, const T *v)
45 { func(user_data, v[0], v[1], v[2]); }
46
47 template<typename T, void (*func)(void *, T, T, T, T)>
48 void wrap_array(void *user_data, const T *v)
49 { func(user_data, v[0], v[1], v[2], v[3]); }
50
51 }
52
53
54 Vector3::Vector3():
55         x(0), y(0), z(0)
56 { }
57
58
59 Vector4::Vector4():
60         x(0), y(0), z(0), w(1)
61 { }
62
63
64 GlState::GlState():
65         decoder(gldecoder_new(this, NULL)),
66         active_tex(0),
67         client_active_tex(0),
68         array_buffer(0),
69         element_buffer(0)
70 {
71         vertex_array.kind = GL_VERTEX_ARRAY;
72         normal_array.kind = GL_NORMAL_ARRAY;
73         color_array.kind = GL_COLOR_ARRAY;
74         for(unsigned i=0; i<8; ++i)
75         {
76                 texcoord_arrays[i].kind = GL_TEXTURE_COORD_ARRAY;
77                 texcoord_arrays[i].index = i;
78         }
79
80         decoder->glEnableClientState = glEnableClientState;
81         decoder->glDisableClientState = glDisableClientState;
82         decoder->glEnableVertexAttribArray = glEnableVertexAttribArray;
83         decoder->glEnableVertexAttribArrayARB = glEnableVertexAttribArray;
84         decoder->glDisableVertexAttribArray = glDisableVertexAttribArray;
85         decoder->glDisableVertexAttribArrayARB = glDisableVertexAttribArray;
86
87         decoder->glColor3ub = wrap_normalized<GLubyte, glColor3f>;
88         decoder->glColor3ubv = wrap_array<GLubyte, wrap_normalized<GLubyte, glColor3f> >;
89         decoder->glColor4ub = wrap_normalized<GLubyte, glColor4f>;
90         decoder->glColor4ubv = wrap_array<GLubyte, wrap_normalized<GLubyte, glColor4f> >;
91         decoder->glColor3f = glColor3f;
92         decoder->glColor3fv = wrap_array<float, glColor3f>;
93         decoder->glColor4f = glColor4f;
94         decoder->glColor4fv = wrap_array<float, glColor4f>;
95         decoder->glTexCoord1f = glTexCoord1f;
96         decoder->glTexCoord1fv = wrap_array<float, glTexCoord1f>;
97         decoder->glTexCoord2f = glTexCoord2f;
98         decoder->glTexCoord2fv = wrap_array<float, glTexCoord2f>;
99         decoder->glTexCoord3f = glTexCoord3f;
100         decoder->glTexCoord3fv = wrap_array<float, glTexCoord3f>;
101         decoder->glTexCoord4f = glTexCoord4f;
102         decoder->glTexCoord4fv = wrap_array<float, glTexCoord4f>;
103         decoder->glNormal3f = glNormal3f;
104         decoder->glNormal3fv = wrap_array<float, glNormal3f>;
105
106         decoder->glActiveTexture = glActiveTexture;
107         decoder->glActiveTextureARB = glActiveTexture;
108         decoder->glBindTexture = glBindTexture;
109         decoder->glTexImage2D = glTexImage2D;
110         decoder->glTexParameteri = glTexParameteri;
111         decoder->glTexParameteriv = glTexParameteriv;
112         decoder->glDeleteTextures = glDeleteTextures;
113
114         decoder->glVertexPointer = glVertexPointer;
115         decoder->glNormalPointer = glNormalPointer;
116         decoder->glColorPointer = glColorPointer;
117         decoder->glClientActiveTexture = glClientActiveTexture;
118         decoder->glClientActiveTextureARB = glClientActiveTexture;
119         decoder->glTexCoordPointer = glTexCoordPointer;
120         decoder->glVertexAttribPointer = glVertexAttribPointer;
121         decoder->glVertexAttribPointerARB = glVertexAttribPointer;
122
123         decoder->glBindBuffer = glBindBuffer;
124         decoder->glBindBufferARB = glBindBuffer;
125         decoder->glBufferData = glBufferData;
126         decoder->glBufferDataARB = glBufferData;
127         decoder->glBufferSubData = glBufferSubData;
128         decoder->glBufferSubDataARB = glBufferSubData;
129         decoder->glDeleteBuffers = glDeleteBuffers;
130         decoder->glDeleteBuffersARB = glDeleteBuffers;
131
132         decoder->glDrawElements = glDrawElements;
133         decoder->glDrawRangeElements = glDrawRangeElements;
134         decoder->glDrawRangeElementsEXT = glDrawRangeElements;
135 }
136
137 GlState::~GlState()
138 {
139         gldecoder_delete(decoder);
140 }
141
142 int GlState::decode(const char *data, unsigned len)
143 {
144         return gldecoder_decode(decoder, data, len);
145 }
146
147 const TextureState &GlState::get_texture(unsigned id) const
148 {
149         TextureMap::const_iterator i = textures.find(id);
150         if(i==textures.end())
151                 throw runtime_error("Unknown texture");
152         return i->second;
153 }
154
155 const BufferState &GlState::get_buffer(unsigned id) const
156 {
157         BufferMap::const_iterator i = buffers.find(id);
158         if(i==buffers.end())
159                 throw runtime_error("Unknown buffer");
160         return i->second;
161 }
162
163 const ArrayState &GlState::get_array(GLenum array) const
164 {
165         if(array==GL_VERTEX_ARRAY)
166                 return vertex_array;
167         else if(array==GL_NORMAL_ARRAY)
168                 return normal_array;
169         else if(array==GL_COLOR_ARRAY)
170                 return color_array;
171         else if(array==GL_TEXTURE_COORD_ARRAY)
172                 return texcoord_arrays[client_active_tex];
173         else
174                 throw logic_error("Invalid array");
175 }
176
177 const ArrayState &GlState::get_texture_coord_array(unsigned index) const
178 {
179         return texcoord_arrays[index];
180 }
181
182 const ArrayState &GlState::get_attrib_array(unsigned index) const
183 {
184         map<unsigned, ArrayState>::const_iterator i = attrib_arrays.find(index);
185         if(i!=attrib_arrays.end())
186                 return i->second;
187
188         // XXX Return a dummy?
189         throw runtime_error("Unknown attribute array");
190 }
191
192 const BufferState *GlState::get_current_buffer(GLenum target) const
193 {
194         return const_cast<GlState *>(this)->get_current_buffer(target);
195 }
196
197 bool &GlState::get_boolean_state(GLenum state)
198 {
199         if(state==GL_VERTEX_ARRAY)
200                 return vertex_array.enabled;
201         else if(state==GL_NORMAL_ARRAY)
202                 return normal_array.enabled;
203         else if(state==GL_COLOR_ARRAY)
204                 return color_array.enabled;
205         else if(state==GL_TEXTURE_COORD_ARRAY)
206                 return texcoord_arrays[client_active_tex].enabled;
207
208         static bool dummy;
209         return dummy;
210 }
211
212 TextureState *GlState::get_current_texture(GLenum target)
213 {
214         return texunits[active_tex].get_current_texture(target);
215 }
216
217 BufferState *GlState::get_current_buffer(GLenum target)
218 {
219         if(target==GL_ARRAY_BUFFER)
220                 return array_buffer;
221         else if(target==GL_ELEMENT_ARRAY_BUFFER)
222                 return element_buffer;
223         return 0;
224 }
225
226 void GlState::set_current_texture(GLenum target, unsigned id)
227 {
228         TexUnitState &unit = texunits[active_tex];
229         TextureState *tex = 0;
230         if(id)
231         {
232                 tex = &textures[id];
233                 if(!tex->id)
234                 {
235                         tex->id = id;
236                         tex->target = target;
237                 }
238                 else if(tex->target!=target)
239                         return;
240         }
241         unit.set_current_texture(target, tex);
242 }
243
244 void GlState::set_current_buffer(GLenum target, unsigned id)
245 {
246         BufferState *buf = 0;
247         if(id)
248         {
249                 buf = &buffers[id];
250                 if(!buf->id)
251                         buf->id = id;
252         }
253
254         if(target==GL_ARRAY_BUFFER)
255                 array_buffer = buf;
256         else if(target==GL_ELEMENT_ARRAY_BUFFER)
257                 element_buffer = buf;
258 }
259
260 ArrayState &GlState::get_attrib_array(unsigned index)
261 {
262         map<unsigned, ArrayState>::iterator i = attrib_arrays.find(index);
263         if(i!=attrib_arrays.end())
264                 return i->second;
265
266         ArrayState &array = attrib_arrays[index];
267         array.index = index;
268
269         return array;
270 }
271
272 // Boolean state
273
274 void GlState::glEnableClientState(void *user_data, GLenum state)
275 {
276         reinterpret_cast<GlState *>(user_data)->get_boolean_state(state) = true;
277 }
278
279 void GlState::glDisableClientState(void *user_data, GLenum state)
280 {
281         reinterpret_cast<GlState *>(user_data)->get_boolean_state(state) = false;
282 }
283
284 void GlState::glEnableVertexAttribArray(void *user_data, unsigned index)
285 {
286         reinterpret_cast<GlState *>(user_data)->attrib_arrays[index].enabled = true;
287 }
288
289 void GlState::glDisableVertexAttribArray(void *user_data, unsigned index)
290 {
291         reinterpret_cast<GlState *>(user_data)->attrib_arrays[index].enabled = false;
292 }
293
294 // Vertex attributes
295
296 void GlState::glColor3f(void *user_data, float r, float g, float b)
297 { glColor4f(user_data, r, g, b, 1.0f); }
298
299 void GlState::glColor4f(void *user_data, float r, float g, float b, float a)
300 {
301         Vector4 &color = reinterpret_cast<GlState *>(user_data)->color;
302         color.r = r;
303         color.g = g;
304         color.b = b;
305         color.a = a;
306 }
307
308 void GlState::glNormal3f(void *user_data, float x, float y, float z)
309 {
310         Vector3 &normal = reinterpret_cast<GlState *>(user_data)->normal;
311         normal.x = x;
312         normal.y = y;
313         normal.z = z;
314 }
315
316 void GlState::glTexCoord1f(void *user_data, float s)
317 { glTexCoord4f(user_data, s, 0.0f, 0.0f, 1.0f); }
318
319 void GlState::glTexCoord2f(void *user_data, float s, float t)
320 { glTexCoord4f(user_data, s, t, 0.0f, 1.0f); }
321
322 void GlState::glTexCoord3f(void *user_data, float s, float t, float p)
323 { glTexCoord4f(user_data, s, t, p, 1.0f); }
324
325 void GlState::glTexCoord4f(void *user_data, float s, float t, float p, float q)
326 {
327         unsigned index = reinterpret_cast<GlState *>(user_data)->active_tex;
328         glMultiTexCoord4f(user_data, index, s, t, p, q);
329 }
330
331 void GlState::glMultiTexCoord4f(void *user_data, unsigned index, float s, float t, float p, float q)
332 {
333         Vector4 &texcoord = reinterpret_cast<GlState *>(user_data)->texcoord[index];
334         texcoord.s = s;
335         texcoord.t = t;
336         texcoord.p = p;
337         texcoord.q = q;
338 }
339
340 // Textures
341
342 void GlState::glActiveTexture(void *user_data, unsigned index)
343 {
344         reinterpret_cast<GlState *>(user_data)->active_tex = index-GL_TEXTURE0;
345 }
346
347 void GlState::glBindTexture(void *user_data, GLenum target, unsigned id)
348 {
349         reinterpret_cast<GlState *>(user_data)->set_current_texture(target, id);
350 }
351
352 void GlState::glTexImage2D(void *user_data, GLenum target, int level, int ifmt, int width, int height, int, GLenum, GLenum, const void *)
353 {
354         if(TextureState *tex = reinterpret_cast<GlState *>(user_data)->get_current_texture(target))
355                 tex->set_image_2d(level, ifmt, width, height);
356 }
357
358 void GlState::glTexParameteri(void *user_data, GLenum target, GLenum param, int value)
359 { glTexParameteriv(user_data, target, param, &value); }
360
361 void GlState::glTexParameteriv(void *user_data, GLenum target, GLenum param, const int *values)
362 {
363         if(TextureState *tex = reinterpret_cast<GlState *>(user_data)->get_current_texture(target))
364                 tex->set_parameter(param, values);
365 }
366
367 void GlState::glDeleteTextures(void *user_data, int count, const unsigned *ids)
368 {
369         for(int i=0; i<count; ++i)
370                 reinterpret_cast<GlState *>(user_data)->textures.erase(ids[i]);
371 }
372
373 // Vertex arrays
374
375 void GlState::glVertexPointer(void *user_data, int size, GLenum type, int stride, const void *data)
376 {
377         GlState *self = reinterpret_cast<GlState *>(user_data);
378         self->vertex_array.set(size, type, false, stride, self->array_buffer, reinterpret_cast<long>(data));
379 }
380
381 void GlState::glNormalPointer(void *user_data, GLenum type, int stride, const void *data)
382 {
383         GlState *self = reinterpret_cast<GlState *>(user_data);
384         self->normal_array.set(3, type, true, stride, self->array_buffer, reinterpret_cast<long>(data));
385 }
386
387 void GlState::glColorPointer(void *user_data, int size, GLenum type, int stride, const void *data)
388 {
389         GlState *self = reinterpret_cast<GlState *>(user_data);
390         self->color_array.set(size, type, true, stride, self->array_buffer, reinterpret_cast<long>(data));
391 }
392
393 void GlState::glClientActiveTexture(void *user_data, unsigned index)
394 {
395         reinterpret_cast<GlState *>(user_data)->client_active_tex = index-GL_TEXTURE0;
396 }
397
398 void GlState::glTexCoordPointer(void *user_data, int size, GLenum type, int stride, const void *data)
399 {
400         GlState *self = reinterpret_cast<GlState *>(user_data);
401         self->texcoord_arrays[self->client_active_tex].set(size, type, false, stride, self->array_buffer, reinterpret_cast<long>(data));
402 }
403
404 void GlState::glVertexAttribPointer(void *user_data, unsigned index, int size, GLenum type, unsigned char norm, int stride, const void *data)
405 {
406         GlState *self = reinterpret_cast<GlState *>(user_data);
407         self->get_attrib_array(index).set(size, type, norm, stride, self->array_buffer, reinterpret_cast<long>(data));
408 }
409
410 // Buffer objects
411
412 void GlState::glBindBuffer(void *user_data, GLenum target, unsigned id)
413 { reinterpret_cast<GlState *>(user_data)->set_current_buffer(target, id); }
414
415 void GlState::glBufferData(void *user_data, GLenum target, int size, const void *data, GLenum usage)
416 {
417         if(BufferState *buf = reinterpret_cast<GlState *>(user_data)->get_current_buffer(target))
418                 buf->set_data(size, data, usage);
419 }
420
421 void GlState::glBufferSubData(void *user_data, GLenum target, int offset, int size, const void *data)
422 {
423         if(BufferState *buf = reinterpret_cast<GlState *>(user_data)->get_current_buffer(target))
424                 buf->set_sub_data(offset, size, data);
425 }
426
427 void GlState::glDeleteBuffers(void *user_data, int count, const unsigned *ids)
428 {
429         for(int i=0; i<count; ++i)
430                 reinterpret_cast<GlState *>(user_data)->buffers.erase(ids[i]);
431 }
432
433 void GlState::glDrawElements(void *user_data, GLenum, int, GLenum type, const void *)
434 {
435         if(BufferState *buf = reinterpret_cast<GlState *>(user_data)->element_buffer)
436                 buf->content.update_elements(type);
437 }
438
439 void GlState::glDrawRangeElements(void *user_data, GLenum, unsigned, unsigned, int, GLenum type, const void *)
440 {
441         if(BufferState *buf = reinterpret_cast<GlState *>(user_data)->element_buffer)
442                 buf->content.update_elements(type);
443 }