]> git.cworth.org Git - apitrace/blob - helpers/glsize.hpp
5eac78e5d644da0813eb379c4968c185bbd6ac7b
[apitrace] / helpers / glsize.hpp
1 /**************************************************************************
2  *
3  * Copyright 2011 Jose Fonseca
4  * Copyright 2010 VMware, Inc.
5  * Copyright 2004 IBM Corporation
6  * All Rights Reserved.
7  * 
8  * Permission is hereby granted, free of charge, to any person obtaining a
9  * copy of this software and associated documentation files (the "Software"),
10  * to deal in the Software without restriction, including without limitation
11  * the rights to use, copy, modify, merge, publish, distribute, sub license,
12  * and/or sell copies of the Software, and to permit persons to whom the
13  * Software is furnished to do so, subject to the following conditions:
14  * 
15  * The above copyright notice and this permission notice (including the next
16  * paragraph) shall be included in all copies or substantial portions of the
17  * Software.
18  * 
19  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.  IN NO EVENT SHALL
22  * AUTHORS,
23  * AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
24  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
25  * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26  * SOFTWARE.
27  *
28  **************************************************************************/
29
30 /*
31  * Auxiliary functions to compute the size of array/blob arguments, depending.
32  */
33
34 #ifndef _GL_SIZE_HPP_
35 #define _GL_SIZE_HPP_
36
37
38 #include <string.h>
39 #include <assert.h>
40
41 #include <algorithm>
42
43 #include "os.hpp"
44 #include "glimports.hpp"
45
46
47 static inline size_t
48 _gl_type_size(GLenum type)
49 {
50     switch (type) {
51     case GL_BOOL:
52     case GL_BYTE:
53     case GL_UNSIGNED_BYTE:
54         return 1;
55     case GL_SHORT:
56     case GL_UNSIGNED_SHORT:
57     case GL_2_BYTES:
58     case GL_HALF_FLOAT:
59         return 2;
60     case GL_3_BYTES:
61         return 3;
62     case GL_INT:
63     case GL_UNSIGNED_INT:
64     case GL_FLOAT:
65     case GL_4_BYTES:
66     case GL_FIXED:
67         return 4;
68     case GL_DOUBLE:
69         return 8;
70     default:
71         os::log("apitrace: warning: %s: unknown GLenum 0x%04X\n", __FUNCTION__, type);
72         return 0;
73     }
74 }
75
76 static inline void
77 _gl_uniform_size(GLenum type, GLenum &elemType, GLint &numCols, GLint &numRows) {
78     numCols = 1;
79     numRows = 1;
80
81     switch (type) {
82     case GL_FLOAT:
83         elemType = GL_FLOAT;
84         break;
85     case GL_FLOAT_VEC2:
86         elemType = GL_FLOAT;
87         numCols = 2;
88         break;
89     case GL_FLOAT_VEC3:
90         elemType = GL_FLOAT;
91         numCols = 3;
92         break;
93     case GL_FLOAT_VEC4:
94         elemType = GL_FLOAT;
95         numCols = 4;
96         break;
97     case GL_DOUBLE:
98         elemType = GL_DOUBLE;
99         break;
100     case GL_DOUBLE_VEC2:
101         elemType = GL_DOUBLE;
102         numCols = 2;
103         break;
104     case GL_DOUBLE_VEC3:
105         elemType = GL_DOUBLE;
106         numCols = 3;
107         break;
108     case GL_DOUBLE_VEC4:
109         elemType = GL_DOUBLE;
110         numCols = 4;
111         break;
112     case GL_INT:
113         elemType = GL_INT;
114         break;
115     case GL_INT_VEC2:
116         elemType = GL_INT;
117         numCols = 2;
118         break;
119     case GL_INT_VEC3:
120         elemType = GL_INT;
121         numCols = 3;
122         break;
123     case GL_INT_VEC4:
124         elemType = GL_INT;
125         numCols = 4;
126         break;
127     case GL_UNSIGNED_INT:
128         elemType = GL_UNSIGNED_INT;
129         break;
130     case GL_UNSIGNED_INT_VEC2:
131         elemType = GL_UNSIGNED_INT;
132         numCols = 2;
133         break;
134     case GL_UNSIGNED_INT_VEC3:
135         elemType = GL_UNSIGNED_INT;
136         numCols = 3;
137         break;
138     case GL_UNSIGNED_INT_VEC4:
139         elemType = GL_UNSIGNED_INT;
140         numCols = 4;
141         break;
142     case GL_BOOL:
143         elemType = GL_BOOL;
144         break;
145     case GL_BOOL_VEC2:
146         elemType = GL_BOOL;
147         numCols = 2;
148         break;
149     case GL_BOOL_VEC3:
150         elemType = GL_BOOL;
151         numCols = 3;
152         break;
153     case GL_BOOL_VEC4:
154         elemType = GL_BOOL;
155         numCols = 4;
156         break;
157     case GL_FLOAT_MAT2:
158         elemType = GL_FLOAT;
159         numCols = 2;
160         numRows = 2;
161         break;
162     case GL_FLOAT_MAT3:
163         elemType = GL_FLOAT;
164         numCols = 3;
165         numRows = 3;
166         break;
167     case GL_FLOAT_MAT4:
168         elemType = GL_FLOAT;
169         numCols = 4;
170         numRows = 4;
171         break;
172     case GL_FLOAT_MAT2x3:
173         elemType = GL_FLOAT;
174         numCols = 2;
175         numRows = 3;
176         break;
177     case GL_FLOAT_MAT2x4:
178         elemType = GL_FLOAT;
179         numCols = 2;
180         numRows = 4;
181         break;
182     case GL_FLOAT_MAT3x2:
183         elemType = GL_FLOAT;
184         numCols = 3;
185         numRows = 2;
186         break;
187     case GL_FLOAT_MAT3x4:
188         elemType = GL_FLOAT;
189         numCols = 3;
190         numRows = 4;
191         break;
192     case GL_FLOAT_MAT4x2:
193         elemType = GL_FLOAT;
194         numCols = 4;
195         numRows = 2;
196         break;
197     case GL_FLOAT_MAT4x3:
198         elemType = GL_FLOAT;
199         numCols = 4;
200         numRows = 3;
201         break;
202     case GL_DOUBLE_MAT2:
203         elemType = GL_DOUBLE;
204         numCols = 2;
205         numRows = 2;
206         break;
207     case GL_DOUBLE_MAT3:
208         elemType = GL_DOUBLE;
209         numCols = 3;
210         numRows = 3;
211         break;
212     case GL_DOUBLE_MAT4:
213         elemType = GL_DOUBLE;
214         numCols = 4;
215         numRows = 4;
216         break;
217     case GL_DOUBLE_MAT2x3:
218         elemType = GL_DOUBLE;
219         numCols = 2;
220         numRows = 3;
221         break;
222     case GL_DOUBLE_MAT2x4:
223         elemType = GL_DOUBLE;
224         numCols = 2;
225         numRows = 4;
226         break;
227     case GL_DOUBLE_MAT3x2:
228         elemType = GL_DOUBLE;
229         numCols = 3;
230         numRows = 2;
231         break;
232     case GL_DOUBLE_MAT3x4:
233         elemType = GL_DOUBLE;
234         numCols = 3;
235         numRows = 4;
236         break;
237     case GL_DOUBLE_MAT4x2:
238         elemType = GL_DOUBLE;
239         numCols = 4;
240         numRows = 2;
241         break;
242     case GL_DOUBLE_MAT4x3:
243         elemType = GL_DOUBLE;
244         numCols = 4;
245         numRows = 3;
246         break;
247     case GL_SAMPLER_1D:
248     case GL_SAMPLER_2D:
249     case GL_SAMPLER_3D:
250     case GL_SAMPLER_CUBE:
251     case GL_SAMPLER_1D_SHADOW:
252     case GL_SAMPLER_2D_SHADOW:
253     case GL_SAMPLER_1D_ARRAY:
254     case GL_SAMPLER_2D_ARRAY:
255     case GL_SAMPLER_CUBE_MAP_ARRAY:
256     case GL_SAMPLER_1D_ARRAY_SHADOW:
257     case GL_SAMPLER_2D_ARRAY_SHADOW:
258     case GL_SAMPLER_2D_MULTISAMPLE:
259     case GL_SAMPLER_2D_MULTISAMPLE_ARRAY:
260     case GL_SAMPLER_CUBE_SHADOW:
261     case GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW:
262     case GL_SAMPLER_BUFFER:
263     case GL_SAMPLER_2D_RECT:
264     case GL_SAMPLER_2D_RECT_SHADOW:
265     case GL_INT_SAMPLER_1D:
266     case GL_INT_SAMPLER_2D:
267     case GL_INT_SAMPLER_3D:
268     case GL_INT_SAMPLER_CUBE:
269     case GL_INT_SAMPLER_1D_ARRAY:
270     case GL_INT_SAMPLER_2D_ARRAY:
271     case GL_INT_SAMPLER_CUBE_MAP_ARRAY:
272     case GL_INT_SAMPLER_2D_MULTISAMPLE:
273     case GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY:
274     case GL_INT_SAMPLER_BUFFER:
275     case GL_INT_SAMPLER_2D_RECT:
276     case GL_UNSIGNED_INT_SAMPLER_1D:
277     case GL_UNSIGNED_INT_SAMPLER_2D:
278     case GL_UNSIGNED_INT_SAMPLER_3D:
279     case GL_UNSIGNED_INT_SAMPLER_CUBE:
280     case GL_UNSIGNED_INT_SAMPLER_1D_ARRAY:
281     case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY:
282     case GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY:
283     case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE:
284     case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY:
285     case GL_UNSIGNED_INT_SAMPLER_BUFFER:
286     case GL_UNSIGNED_INT_SAMPLER_2D_RECT:
287         elemType = GL_INT;
288         break;
289     default:
290         os::log("apitrace: warning: %s: unknown GLenum 0x%04X\n", __FUNCTION__, type);
291         elemType = GL_NONE;
292         numCols = 0;
293         numRows = 0;
294         return;
295     }
296 }
297     
298 static inline size_t
299 _glArrayPointer_size(GLint size, GLenum type, GLsizei stride, GLsizei count)
300 {
301     if (!count) {
302         return 0;
303     }
304
305     if (size == GL_BGRA) {
306         size = 4; 
307     }
308
309     if (size > 4) {
310         os::log("apitrace: warning: %s: unexpected size 0x%04X\n", __FUNCTION__, size);
311     }
312
313     size_t elementSize = size*_gl_type_size(type);
314     if (!stride) {
315         stride = (GLsizei)elementSize;
316     }
317
318     return stride*(count - 1) + elementSize;
319 }
320
321 #define _glVertexPointer_size(size, type, stride, count) _glArrayPointer_size(size, type, stride, count)
322 #define _glNormalPointer_size(type, stride, count) _glArrayPointer_size(3, type, stride, count)
323 #define _glColorPointer_size(size, type, stride, count) _glArrayPointer_size(size, type, stride, count)
324 #define _glIndexPointer_size(type, stride, count) _glArrayPointer_size(1, type, stride, count)
325 #define _glTexCoordPointer_size(size, type, stride, count) _glArrayPointer_size(size, type, stride, count)
326 #define _glEdgeFlagPointer_size(stride, count) _glArrayPointer_size(1, GL_BOOL, stride, count)
327 #define _glFogCoordPointer_size(type, stride, count) _glArrayPointer_size(1, type, stride, count)
328 #define _glSecondaryColorPointer_size(size, type, stride, count) _glArrayPointer_size(size, type, stride, count)
329 #define _glVertexAttribPointer_size(size, type, normalized, stride, count) _glArrayPointer_size(size, type, stride, count)
330 #define _glVertexAttribPointerARB_size(size, type, normalized, stride, count) _glArrayPointer_size(size, type, stride, count)
331 #define _glVertexAttribPointerNV_size(size, type, stride, count) _glArrayPointer_size(size, type, stride, count)
332
333 /**
334  * Same as glGetIntegerv, but passing the result in the return value.
335  */
336 static inline GLint
337 _glGetInteger(GLenum pname) {
338     GLint param = 0;
339     _glGetIntegerv(pname, &param);
340     return param;
341 }
342
343 static inline GLint
344 _element_array_buffer_binding(void) {
345     return _glGetInteger(GL_ELEMENT_ARRAY_BUFFER_BINDING);
346 }
347
348 static inline GLuint
349 _glDrawArrays_count(GLint first, GLsizei count)
350 {
351     if (!count) {
352         return 0;
353     }
354     return first + count;
355 }
356
357 #define _glDrawArraysEXT_count _glDrawArrays_count
358
359 /* Forward declaration for definition in gltrace.py */
360 void
361 _shadow_glGetBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size,
362                               GLvoid *data);
363
364 static inline GLuint
365 _glDrawElementsBaseVertex_count(GLsizei count, GLenum type, const GLvoid *indices, GLint basevertex)
366 {
367     GLvoid *temp = 0;
368
369     if (!count) {
370         return 0;
371     }
372
373     GLint element_array_buffer = _element_array_buffer_binding();
374     if (element_array_buffer) {
375         // Read indices from index buffer object
376         GLintptr offset = (GLintptr)indices;
377         GLsizeiptr size = count*_gl_type_size(type);
378         GLvoid *temp = malloc(size);
379         if (!temp) {
380             return 0;
381         }
382         memset(temp, 0, size);
383         _shadow_glGetBufferSubData(GL_ELEMENT_ARRAY_BUFFER, offset, size, temp);
384         indices = temp;
385     } else {
386         if (!indices) {
387             return 0;
388         }
389     }
390
391     GLuint maxindex = 0;
392     GLsizei i;
393     if (type == GL_UNSIGNED_BYTE) {
394         const GLubyte *p = (const GLubyte *)indices;
395         for (i = 0; i < count; ++i) {
396             if (p[i] > maxindex) {
397                 maxindex = p[i];
398             }
399         }
400     } else if (type == GL_UNSIGNED_SHORT) {
401         const GLushort *p = (const GLushort *)indices;
402         for (i = 0; i < count; ++i) {
403             if (p[i] > maxindex) {
404                 maxindex = p[i];
405             }
406         }
407     } else if (type == GL_UNSIGNED_INT) {
408         const GLuint *p = (const GLuint *)indices;
409         for (i = 0; i < count; ++i) {
410             if (p[i] > maxindex) {
411                 maxindex = p[i];
412             }
413         }
414     } else {
415         os::log("apitrace: warning: %s: unknown GLenum 0x%04X\n", __FUNCTION__, type);
416     }
417
418     if (element_array_buffer) {
419         free(temp);
420     }
421
422     maxindex += basevertex;
423
424     return maxindex + 1;
425 }
426
427 #define _glDrawRangeElementsBaseVertex_count(start, end, count, type, indices, basevertex) _glDrawElementsBaseVertex_count(count, type, indices, basevertex)
428
429 #define _glDrawElements_count(count, type, indices) _glDrawElementsBaseVertex_count(count, type, indices, 0);
430 #define _glDrawRangeElements_count(start, end, count, type, indices) _glDrawElements_count(count, type, indices)
431 #define _glDrawRangeElementsEXT_count _glDrawRangeElements_count
432
433 /* FIXME take in consideration instancing */
434 #define _glDrawArraysInstanced_count(first, count, primcount) _glDrawArrays_count(first, count)
435 #define _glDrawElementsInstanced_count(count, type, indices, primcount) _glDrawElements_count(count, type, indices)
436 #define _glDrawElementsInstancedBaseVertex_count(count, type, indices, primcount, basevertex) _glDrawElementsBaseVertex_count(count, type, indices, basevertex)
437 #define _glDrawRangeElementsInstanced_count(start, end, count, type, indices, primcount) _glDrawRangeElements_count(start, end, count, type, indices)
438 #define _glDrawRangeElementsInstancedBaseVertex_count(start, end, count, type, indices, primcount, basevertex) _glDrawRangeElementsBaseVertex_count(start, end, count, type, indices, basevertex)
439
440 #define _glDrawArraysInstancedBaseInstance_count(first, count, primcount, baseinstance) _glDrawArrays_count(first, count)
441 #define _glDrawElementsInstancedBaseInstance_count(count, type, indices, primcount, baseinstance) _glDrawElements_count(count, type, indices)
442 #define _glDrawElementsInstancedBaseVertexBaseInstance_count(count, type, indices, primcount, basevertex, baseinstance) _glDrawElementsBaseVertex_count(count, type, indices, basevertex)
443
444 #define _glDrawArraysInstancedARB_count _glDrawArraysInstanced_count
445 #define _glDrawElementsInstancedARB_count _glDrawElementsInstanced_count
446 #define _glDrawArraysInstancedEXT_count _glDrawArraysInstanced_count
447 #define _glDrawElementsInstancedEXT_count _glDrawElementsInstanced_count
448
449 typedef struct {
450     GLuint count;
451     GLuint primCount;
452     GLuint first;
453     GLuint baseInstance;
454 } DrawArraysIndirectCommand;
455
456 static inline GLuint
457 _glMultiDrawArraysIndirect_count(const GLvoid *indirect, GLsizei drawcount, GLsizei stride) {
458     const DrawArraysIndirectCommand *cmd;
459     GLvoid *temp = 0;
460
461     if (drawcount <= 0) {
462         return 0;
463     }
464
465     if (stride == 0) {
466         stride = sizeof *cmd;
467     }
468
469     GLint draw_indirect_buffer = _glGetInteger(GL_DRAW_INDIRECT_BUFFER_BINDING);
470     if (draw_indirect_buffer) {
471         // Read commands from indirect buffer object
472         GLintptr offset = (GLintptr)indirect;
473         GLsizeiptr size = sizeof *cmd + (drawcount - 1) * stride;
474         GLvoid *temp = malloc(size);
475         if (!temp) {
476             return 0;
477         }
478         memset(temp, 0, size);
479         _glGetBufferSubData(GL_DRAW_INDIRECT_BUFFER, offset, size, temp);
480         indirect = temp;
481     } else {
482         if (!indirect) {
483             return 0;
484         }
485     }
486
487     GLuint count = 0;
488     for (GLsizei i = 0; i < drawcount; ++i) {
489         cmd = (const DrawArraysIndirectCommand *)((const GLbyte *)indirect + i * stride);
490
491         GLuint count_i = _glDrawArraysInstancedBaseInstance_count(
492             cmd->first,
493             cmd->count,
494             cmd->primCount,
495             cmd->baseInstance
496         );
497
498         count = std::max(count, count_i);
499     }
500
501     if (draw_indirect_buffer) {
502         free(temp);
503     }
504
505     return count;
506 }
507
508 static inline GLuint
509 _glDrawArraysIndirect_count(const GLvoid *indirect) {
510     return _glMultiDrawArraysIndirect_count(indirect, 1, 0);
511 }
512
513 typedef struct {
514     GLuint count;
515     GLuint primCount;
516     GLuint firstIndex;
517     GLuint baseVertex;
518     GLuint baseInstance;
519 } DrawElementsIndirectCommand;
520
521 static inline GLuint
522 _glMultiDrawElementsIndirect_count(GLenum type, const GLvoid *indirect, GLsizei drawcount, GLsizei stride) {
523     const DrawElementsIndirectCommand *cmd;
524     GLvoid *temp = 0;
525
526     if (drawcount <= 0) {
527         return 0;
528     }
529
530     if (stride == 0) {
531         stride = sizeof *cmd;
532     }
533
534     GLint draw_indirect_buffer = _glGetInteger(GL_DRAW_INDIRECT_BUFFER_BINDING);
535     if (draw_indirect_buffer) {
536         // Read commands from indirect buffer object
537         GLintptr offset = (GLintptr)indirect;
538         GLsizeiptr size = sizeof *cmd + (drawcount - 1) * stride;
539         GLvoid *temp = malloc(size);
540         if (!temp) {
541             return 0;
542         }
543         memset(temp, 0, size);
544         _glGetBufferSubData(GL_DRAW_INDIRECT_BUFFER, offset, size, temp);
545         indirect = temp;
546     } else {
547         if (!indirect) {
548             return 0;
549         }
550     }
551
552     cmd = (const DrawElementsIndirectCommand *)indirect;
553
554     GLuint count = 0;
555     for (GLsizei i = 0; i < drawcount; ++i) {
556         cmd = (const DrawElementsIndirectCommand *)((const GLbyte *)indirect + i * stride);
557
558         GLuint count_i = _glDrawElementsInstancedBaseVertexBaseInstance_count(
559             cmd->count,
560             type,
561             (GLvoid *)(uintptr_t)(cmd->firstIndex * _gl_type_size(type)),
562             cmd->primCount,
563             cmd->baseVertex,
564             cmd->baseInstance
565         );
566
567         count = std::max(count, count_i);
568     }
569
570     if (draw_indirect_buffer) {
571         free(temp);
572     }
573
574     return count;
575 }
576
577 static inline GLuint
578 _glDrawElementsIndirect_count(GLenum type, const GLvoid *indirect) {
579     return _glMultiDrawElementsIndirect_count(type, indirect, 1, 0);
580 }
581
582 #define _glMultiDrawArraysIndirectAMD_count _glMultiDrawArraysIndirect_count
583 #define _glMultiDrawElementsIndirectAMD_count _glMultiDrawElementsIndirect_count
584
585 static inline GLuint
586 _glMultiDrawArrays_count(const GLint *first, const GLsizei *count, GLsizei drawcount) {
587     GLuint _count = 0;
588     for (GLsizei draw = 0; draw < drawcount; ++draw) {
589         GLuint _count_draw = _glDrawArrays_count(first[draw], count[draw]);
590         _count = std::max(_count, _count_draw);
591     }
592     return _count;
593 }
594
595 static inline GLuint
596 _glMultiDrawElements_count(const GLsizei *count, GLenum type, const GLvoid* const *indices, GLsizei drawcount) {
597     GLuint _count = 0;
598     for (GLsizei draw = 0; draw < drawcount; ++draw) {
599         GLuint _count_draw = _glDrawElements_count(count[draw], type, indices[draw]);
600         _count = std::max(_count, _count_draw);
601     }
602     return _count;
603 }
604
605 static inline GLuint
606 _glMultiDrawElementsBaseVertex_count(const GLsizei *count, GLenum type, const GLvoid* const *indices, GLsizei drawcount, const GLint * basevertex) {
607     GLuint _count = 0;
608     for (GLsizei draw = 0; draw < drawcount; ++draw) {
609         GLuint _count_draw = _glDrawElementsBaseVertex_count(count[draw], type, indices[draw], basevertex[draw]);
610         _count = std::max(_count, _count_draw);
611     }
612     return _count;
613 }
614
615 #define _glMultiDrawArraysEXT_count _glMultiDrawArrays_count
616 #define _glMultiDrawElementsEXT_count _glMultiDrawElements_count
617
618 #define _glMultiModeDrawArraysIBM_count(first, count, drawcount, modestride) _glMultiDrawArrays_count(first, count, drawcount)
619 #define _glMultiModeDrawElementsIBM_count(count, type, indices, drawcount, modestride) _glMultiDrawElements_count(count, type, (const GLvoid **)indices, drawcount)
620
621
622 static inline size_t
623 _glCallLists_size(GLsizei n, GLenum type)
624 {
625     return n*_gl_type_size(type);
626 }
627
628 static inline size_t
629 _glMap1d_size(GLenum target, GLint stride, GLint order)
630 {
631     if (order < 1) {
632         return 0;
633     }
634
635     GLint channels;
636     switch (target) {
637     case GL_MAP1_INDEX:
638     case GL_MAP1_TEXTURE_COORD_1:
639         channels = 1;
640         break;
641     case GL_MAP1_TEXTURE_COORD_2:
642         channels = 2;
643         break;
644     case GL_MAP1_NORMAL:
645     case GL_MAP1_TEXTURE_COORD_3:
646     case GL_MAP1_VERTEX_3:
647         channels = 3;
648         break;
649     case GL_MAP1_COLOR_4:
650     case GL_MAP1_TEXTURE_COORD_4:
651     case GL_MAP1_VERTEX_4:
652         channels = 4;
653         break;
654     default:
655         os::log("apitrace: warning: %s: unknown GLenum 0x%04X\n", __FUNCTION__, target);
656         return 0;
657     }
658
659     if (stride < channels) {
660         return 0;
661     }
662
663     return channels + stride * (order - 1);
664 }
665
666 #define _glMap1f_size _glMap1d_size
667
668 static inline size_t
669 _glMap2d_size(GLenum target, GLint ustride, GLint uorder, GLint vstride, GLint vorder)
670 {
671     if (uorder < 1 || vorder < 1) {
672         return 0;
673     }
674
675     GLint channels;
676     switch (target) {
677     case GL_MAP2_INDEX:
678     case GL_MAP2_TEXTURE_COORD_1:
679         channels = 1;
680         break;
681     case GL_MAP2_TEXTURE_COORD_2:
682         channels = 2;
683         break;
684     case GL_MAP2_NORMAL:
685     case GL_MAP2_TEXTURE_COORD_3:
686     case GL_MAP2_VERTEX_3:
687         channels = 3;
688         break;
689     case GL_MAP2_COLOR_4:
690     case GL_MAP2_TEXTURE_COORD_4:
691     case GL_MAP2_VERTEX_4:
692         channels = 4;
693         break;
694     default:
695         os::log("apitrace: warning: %s: unknown GLenum 0x%04X\n", __FUNCTION__, target);
696         return 0;
697     }
698
699     if (ustride < channels || vstride < channels) {
700         return 0;
701     }
702
703     return channels + 
704            ustride * (uorder - 1) +
705            vstride * (vorder - 1);
706 }
707
708 #define _glMap2f_size _glMap2d_size
709
710 /**
711  * Number of channels in this format.
712  *
713  * That is, the number of elements per pixel when this format is passed with a
714  * to DrawPixels, ReadPixels, TexImage*, TexSubImage*, GetTexImage, etc.
715  */
716 static inline unsigned
717 _gl_format_channels(GLenum format) {
718     switch (format) {
719     case GL_COLOR_INDEX:
720     case GL_RED:
721     case GL_RED_INTEGER:
722     case GL_GREEN:
723     case GL_GREEN_INTEGER:
724     case GL_BLUE:
725     case GL_BLUE_INTEGER:
726     case GL_ALPHA:
727     case GL_ALPHA_INTEGER:
728     case GL_INTENSITY:
729     case GL_LUMINANCE:
730     case GL_LUMINANCE_INTEGER_EXT:
731     case GL_DEPTH_COMPONENT:
732     case GL_STENCIL_INDEX:
733         return 1;
734     case GL_DEPTH_STENCIL:
735     case GL_LUMINANCE_ALPHA:
736     case GL_LUMINANCE_ALPHA_INTEGER_EXT:
737     case GL_RG:
738     case GL_RG_INTEGER:
739     case GL_422_EXT: // (luminance, chrominance)
740     case GL_422_REV_EXT: // (luminance, chrominance)
741     case GL_422_AVERAGE_EXT: // (luminance, chrominance)
742     case GL_422_REV_AVERAGE_EXT: // (luminance, chrominance)
743     case GL_HILO_NV: // (hi, lo)
744     case GL_DSDT_NV: // (ds, dt)
745     case GL_YCBCR_422_APPLE: // (luminance, chroma)
746     case GL_RGB_422_APPLE: // (G, B) on even pixels, (G, R) on odd pixels
747     case GL_YCRCB_422_SGIX: // (Y, [Cb,Cr])
748         return 2;
749     case GL_RGB:
750     case GL_RGB_INTEGER:
751     case GL_BGR:
752     case GL_BGR_INTEGER:
753     case GL_DSDT_MAG_NV: // (ds, dt, magnitude)
754     case GL_YCRCB_444_SGIX: // (Cb, Y, Cr)
755         return 3;
756     case GL_RGBA:
757     case GL_RGBA_INTEGER:
758     case GL_BGRA:
759     case GL_BGRA_INTEGER:
760     case GL_ABGR_EXT:
761     case GL_CMYK_EXT:
762     case GL_DSDT_MAG_VIB_NV: // (ds, dt, magnitude, vibrance)
763         return 4;
764     case GL_CMYKA_EXT:
765         return 5;
766     case GL_FORMAT_SUBSAMPLE_24_24_OML:
767     case GL_FORMAT_SUBSAMPLE_244_244_OML:
768         // requires UNSIGNED_INT_10_10_10_2, so this value will be ignored
769         return 0;
770     default:
771         os::log("apitrace: warning: %s: unexpected format GLenum 0x%04X\n", __FUNCTION__, format);
772         return 0;
773     }
774 }
775
776 template<class X>
777 static inline bool
778 _is_pot(X x) {
779     return (x & (x - 1)) == 0;
780 }
781
782 template<class X, class Y>
783 static inline X
784 _align(X x, Y y) {
785     return (x + (y - 1)) & ~(y - 1);
786 }
787
788 static inline void
789 _gl_format_size(GLenum format, GLenum type,
790                 unsigned & bits_per_element, unsigned & bits_per_pixel)
791 {
792     unsigned num_channels = _gl_format_channels(format);
793
794     switch (type) {
795     case GL_BITMAP:
796         bits_per_pixel = bits_per_element = 1;
797         break;
798     case GL_BYTE:
799     case GL_UNSIGNED_BYTE:
800         bits_per_element = 8;
801         bits_per_pixel = bits_per_element * num_channels;
802         break;
803     case GL_SHORT:
804     case GL_UNSIGNED_SHORT:
805     case GL_HALF_FLOAT:
806         bits_per_element = 16;
807         bits_per_pixel = bits_per_element * num_channels;
808         break;
809     case GL_INT:
810     case GL_UNSIGNED_INT:
811     case GL_FLOAT:
812         bits_per_element = 32;
813         bits_per_pixel = bits_per_element * num_channels;
814         break;
815     case GL_UNSIGNED_BYTE_3_3_2:
816     case GL_UNSIGNED_BYTE_2_3_3_REV:
817         bits_per_pixel = bits_per_element = 8;
818         break;
819     case GL_UNSIGNED_SHORT_4_4_4_4:
820     case GL_UNSIGNED_SHORT_4_4_4_4_REV:
821     case GL_UNSIGNED_SHORT_5_5_5_1:
822     case GL_UNSIGNED_SHORT_1_5_5_5_REV:
823     case GL_UNSIGNED_SHORT_5_6_5:
824     case GL_UNSIGNED_SHORT_5_6_5_REV:
825     case GL_UNSIGNED_SHORT_8_8_MESA:
826     case GL_UNSIGNED_SHORT_8_8_REV_MESA:
827         bits_per_pixel = bits_per_element = 16;
828         break;
829     case GL_UNSIGNED_INT_8_8_8_8:
830     case GL_UNSIGNED_INT_8_8_8_8_REV:
831     case GL_UNSIGNED_INT_10_10_10_2:
832     case GL_UNSIGNED_INT_2_10_10_10_REV:
833     case GL_UNSIGNED_INT_24_8:
834     case GL_UNSIGNED_INT_10F_11F_11F_REV:
835     case GL_UNSIGNED_INT_5_9_9_9_REV:
836     case GL_UNSIGNED_INT_S8_S8_8_8_NV:
837     case GL_UNSIGNED_INT_8_8_S8_S8_REV_NV:
838         bits_per_pixel = bits_per_element = 32;
839         break;
840     case GL_FLOAT_32_UNSIGNED_INT_24_8_REV:
841         bits_per_pixel = bits_per_element = 64;
842         break;
843     default:
844         os::log("apitrace: warning: %s: unexpected type GLenum 0x%04X\n", __FUNCTION__, type);
845         bits_per_pixel = bits_per_element = 0;
846         break;
847     }
848 }
849
850 static inline size_t
851 _glClearBufferData_size(GLenum format, GLenum type) {
852     unsigned bits_per_element;
853     unsigned bits_per_pixel;
854     _gl_format_size(format, type, bits_per_element, bits_per_pixel);
855     return (bits_per_pixel + 7)/8;
856 }
857
858 static inline size_t
859 _gl_image_size(GLenum format, GLenum type, GLsizei width, GLsizei height, GLsizei depth, GLboolean has_unpack_subimage) {
860
861     unsigned bits_per_element;
862     unsigned bits_per_pixel;
863     _gl_format_size(format, type, bits_per_element, bits_per_pixel);
864
865     GLint alignment = 4;
866     GLint row_length = 0;
867     GLint image_height = 0;
868     GLint skip_rows = 0;
869     GLint skip_pixels = 0;
870     GLint skip_images = 0;
871
872     _glGetIntegerv(GL_UNPACK_ALIGNMENT, &alignment);
873     if (has_unpack_subimage) {
874         _glGetIntegerv(GL_UNPACK_ROW_LENGTH,   &row_length);
875         _glGetIntegerv(GL_UNPACK_IMAGE_HEIGHT, &image_height);
876         _glGetIntegerv(GL_UNPACK_SKIP_ROWS,    &skip_rows);
877         _glGetIntegerv(GL_UNPACK_SKIP_PIXELS,  &skip_pixels);
878         _glGetIntegerv(GL_UNPACK_SKIP_IMAGES,  &skip_images);
879     }
880
881     if (row_length <= 0) {
882         row_length = width;
883     }
884
885     size_t row_stride = (row_length*bits_per_pixel + 7)/8;
886
887     if ((bits_per_element == 1*8 ||
888          bits_per_element == 2*8 ||
889          bits_per_element == 4*8 ||
890          bits_per_element == 8*8) &&
891         (GLint)bits_per_element < alignment*8) {
892         row_stride = _align(row_stride, alignment);
893     }
894
895     if (image_height <= 0) {
896         image_height = height;
897     }
898
899     /* XXX: GL_UNPACK_IMAGE_HEIGHT and GL_UNPACK_SKIP_IMAGES should probably
900      * not be considered for pixel rectangles. */
901
902     size_t image_stride = image_height*row_stride;
903
904     size_t size = depth*image_stride;
905
906     size += (skip_pixels*bits_per_pixel + 7)/8;
907     size += skip_rows*row_stride;
908     size += skip_images*image_stride;
909
910     return size;
911 }
912
913 // note that can_unpack_subimage() is generated by gltrace.py
914 #define _glTexImage3D_size(format, type, width, height, depth) _gl_image_size(format, type, width, height, depth, can_unpack_subimage())
915 #define _glTexImage2D_size(format, type, width, height)        _gl_image_size(format, type, width, height, 1, can_unpack_subimage())
916 #define _glTexImage1D_size(format, type, width)                _gl_image_size(format, type, width, 1, 1, can_unpack_subimage())
917
918 #define _glTexSubImage3D_size(format, type, width, height, depth) _glTexImage3D_size(format, type, width, height, depth)
919 #define _glTexSubImage2D_size(format, type, width, height)        _glTexImage2D_size(format, type, width, height)
920 #define _glTexSubImage1D_size(format, type, width)                _glTexImage1D_size(format, type, width)
921
922 #define _glTexImage3DEXT_size _glTexImage3D_size
923 #define _glTexImage2DEXT_size _glTexImage2D_size
924 #define _glTexImage1DEXT_size _glTexImage1D_size
925 #define _glTexSubImage3DEXT_size _glTexSubImage3D_size
926 #define _glTexSubImage2DEXT_size _glTexSubImage2D_size
927 #define _glTexSubImage1DEXT_size _glTexSubImage1D_size
928
929 #define _glTextureImage3DEXT_size _glTexImage3D_size
930 #define _glTextureImage2DEXT_size _glTexImage2D_size
931 #define _glTextureImage1DEXT_size _glTexImage1D_size
932 #define _glTextureSubImage3DEXT_size _glTexSubImage3D_size
933 #define _glTextureSubImage2DEXT_size _glTexSubImage2D_size
934 #define _glTextureSubImage1DEXT_size _glTexSubImage1D_size
935
936 #define _glMultiTexImage3DEXT_size _glTexImage3D_size
937 #define _glMultiTexImage2DEXT_size _glTexImage2D_size
938 #define _glMultiTexImage1DEXT_size _glTexImage1D_size
939 #define _glMultiTexSubImage3DEXT_size _glTexSubImage3D_size
940 #define _glMultiTexSubImage2DEXT_size _glTexSubImage2D_size
941 #define _glMultiTexSubImage1DEXT_size _glTexSubImage1D_size
942
943 #define _glDrawPixels_size(format, type, width, height) _glTexImage2D_size(format, type, width, height)
944 #define _glConvolutionFilter1D_size(format, type, width) _glTexImage1D_size(format, type, width)
945 #define _glConvolutionFilter2D_size(format, type, width, height) _glTexImage2D_size(format, type, width, height)
946 #define _glColorTable_size(format, type, width) _glTexImage1D_size(format, type, width)
947 #define _glColorSubTable_size(format, type, count) _glColorTable_size(format, type, count)
948
949 #define _glBitmap_size(width, height) _glTexImage2D_size(GL_COLOR_INDEX, GL_BITMAP, width, height)
950 #define _glPolygonStipple_size() _glBitmap_size(32, 32)
951
952 static inline size_t
953 _glClearBuffer_size(GLenum buffer)
954 {
955     switch (buffer) {
956     case GL_COLOR:
957     case GL_FRONT:
958     case GL_BACK:
959     case GL_LEFT:
960     case GL_RIGHT:
961     case GL_FRONT_AND_BACK:
962         return 4;
963     case GL_DEPTH:
964     case GL_STENCIL:
965         return 1;
966     default:
967         os::log("apitrace: warning: %s: unexpected buffer GLenum 0x%04X\n", __FUNCTION__, buffer);
968         return 0;
969     }
970 }
971
972 static inline size_t
973 _glPath_coords_size(GLsizei numCoords, GLenum coordType)
974 {
975     switch (coordType) {
976     case GL_BYTE:
977         return numCoords * sizeof(GLbyte);
978     case GL_UNSIGNED_BYTE:
979         return numCoords * sizeof(GLubyte);
980     case GL_SHORT:
981         return numCoords * sizeof(GLshort);
982     case GL_UNSIGNED_SHORT:
983         return numCoords * sizeof(GLushort);
984     case GL_FLOAT:
985         return numCoords * sizeof(GLfloat);
986     default:
987         return 0;
988     }
989 }
990
991 static inline size_t
992 _glPath_fontName_size(GLenum fontTarget, const void *fontName)
993 {
994     switch (fontTarget) {
995     case GL_STANDARD_FONT_NAME_NV:
996     case GL_SYSTEM_FONT_NAME_NV:
997     case GL_FILE_NAME_NV:
998         {
999             // Include +1 to copy nul terminator.
1000             GLsizei size = GLsizei(strlen(reinterpret_cast<const char*>(fontName))+1);
1001             return size;
1002         }
1003     default:
1004         return 0;
1005     }
1006 }
1007
1008 static inline size_t
1009 _glPath_chardcodes_size(GLsizei numGlyphs, GLenum type)
1010 {
1011     GLsizei bytes_per_glyph;
1012     switch (type) {
1013     case GL_FLOAT:
1014     case GL_INT:
1015         bytes_per_glyph = 4;
1016         break;
1017     case GL_BYTE:
1018         bytes_per_glyph = 1;
1019         break;
1020     case GL_SHORT:
1021         bytes_per_glyph = 2;
1022         break;
1023     default:
1024         return 0;
1025     }
1026     return bytes_per_glyph*numGlyphs;
1027 }
1028
1029 static GLsizei floatPerTransformList(GLenum transformType)
1030 {
1031     switch (transformType) {
1032     case GL_NONE:
1033         return 0;
1034     case GL_TRANSLATE_X_NV:
1035     case GL_TRANSLATE_Y_NV:
1036         return 1;
1037     case GL_TRANSLATE_2D_NV:
1038         return 2;
1039     case GL_TRANSLATE_3D_NV:
1040         return 3;
1041     case GL_AFFINE_2D_NV:
1042     case GL_TRANSPOSE_AFFINE_2D_NV:
1043         return 6;
1044     case GL_PROJECTIVE_2D_NV:
1045     case GL_TRANSPOSE_PROJECTIVE_2D_NV:
1046         return 9;
1047     case GL_AFFINE_3D_NV:
1048     case GL_TRANSPOSE_AFFINE_3D_NV:
1049         return 12;
1050     case GL_PROJECTIVE_3D_NV:
1051     case GL_TRANSPOSE_PROJECTIVE_3D_NV:
1052         return 16;
1053     default:
1054         return 0;
1055     }
1056 }
1057
1058 static inline size_t
1059 _gl_transformType_size(GLenum transformType)
1060 {
1061     return floatPerTransformList(transformType)*sizeof(GLfloat);
1062 }
1063
1064 static inline size_t
1065 _gl_transformType_size(GLsizei numPaths, GLenum transformType)
1066 {
1067     return numPaths*floatPerTransformList(transformType)*sizeof(GLfloat);
1068 }
1069
1070 static size_t valuesPerPathParameter(GLenum pname)
1071 {
1072     switch (pname) {
1073     case GL_PATH_FILL_MODE_NV:
1074     case GL_PATH_FILL_MASK_NV:
1075     case GL_PATH_FILL_COVER_MODE_NV:
1076     case GL_PATH_STROKE_WIDTH_NV:
1077     case GL_PATH_INITIAL_END_CAP_NV:
1078     case GL_PATH_TERMINAL_END_CAP_NV:
1079     case GL_PATH_JOIN_STYLE_NV:
1080     case GL_PATH_MITER_LIMIT_NV:
1081     case GL_PATH_INITIAL_DASH_CAP_NV:
1082     case GL_PATH_TERMINAL_DASH_CAP_NV:
1083     case GL_PATH_DASH_OFFSET_NV:
1084     case GL_PATH_DASH_OFFSET_RESET_NV:
1085     case GL_PATH_CLIENT_LENGTH_NV:
1086     case GL_PATH_STROKE_COVER_MODE_NV:
1087     case GL_PATH_STROKE_MASK_NV:
1088     case GL_PATH_STROKE_OVERSAMPLE_COUNT_NV:
1089     case GL_PATH_SAMPLE_QUALITY_NV:
1090     case GL_PATH_END_CAPS_NV:  // not valid for glGetPathParameter
1091     case GL_PATH_DASH_CAPS_NV: // not valid for glGetPathParameter
1092         return 1;
1093     default:
1094         return 0;
1095     }
1096 }
1097
1098 static inline size_t
1099 _gl_PathParameter_size(GLenum pname)
1100 {
1101     return valuesPerPathParameter(pname);
1102 }
1103
1104 // See RFC-3629 "UTF-8, a transformation format of ISO 10646"
1105 // http://www.rfc-editor.org/rfc/rfc3629.txt
1106 // http://rfc-ref.org/RFC-TEXTS/3629/index.html
1107 static bool
1108 __glPathGetCodePointUTF8(const void *&utf_string,
1109                          GLuint &code_point)
1110 {
1111     const GLubyte *p = reinterpret_cast<const GLubyte*>(utf_string);
1112     GLubyte c0 = p[0];
1113     if ((c0 & 0x80) == 0x00) {
1114         // Zero continuation (0 to 127)
1115         code_point = c0;
1116         assert(code_point <= 127);
1117         p += 1;
1118     } else {
1119         GLubyte c1 = p[1];
1120         if ((c1 & 0xC0) != 0x80) {
1121             // Stop processing the UTF byte sequence early.
1122             return false;
1123         }
1124         if ((c0 & 0xE0) == 0xC0) {
1125             // One contination (128 to 2047)
1126             code_point = ((c0 & 0x1F) << 6) | (c1 & 0x3F);
1127             if (code_point < 128) {
1128                 return false;
1129             }
1130             assert(code_point >= 128 && code_point <= 2047);
1131             p += 2;
1132         } else {
1133             GLubyte c2 = p[2];
1134             if ((c2 & 0xC0) != 0x80) {
1135                 // Stop processing the UTF byte sequence early.
1136                 return false;
1137             }
1138             if ((c0 & 0xF0) == 0xE0) {
1139                 // Two continuation (2048 to 55295 and 57344 to 65535)
1140                 code_point = ((c0 & 0x0F) << 12) |
1141                              ((c1 & 0x3F) << 6) |
1142                               (c2 & 0x3F);
1143                 // "The definition of UTF-8 prohibits encoding character numbers between
1144                 // U+D800 and U+DFFF, which are reserved for use with the UTF-16
1145                 // encoding form (as surrogate pairs) and do not directly represent
1146                 // characters."
1147                 // 0xD800 = 55,296
1148                 // 0xDFFF = 57,343
1149                 if ((code_point >= 55296) && (code_point <= 57343)) {
1150                     // Stop processing the UTF byte sequence early.
1151                     return false;
1152                 }
1153                 if (code_point < 2048) {
1154                     return false;
1155                 }
1156                 assert(code_point >= 2048 && code_point <= 65535);
1157                 assert(code_point < 55296 || code_point > 57343);
1158                 p += 3;
1159             } else {
1160                 GLubyte c3 = p[3];
1161                 if ((c3 & 0xC0) != 0x80) {
1162                     // Stop processing the UTF byte sequence early.
1163                     return false;
1164                 }
1165                 if ((c0 & 0xF8) == 0xF0) {
1166                     // Three continuation (65536 to 1114111)
1167                     code_point = ((c0 & 0x07) << 18) |
1168                                  ((c1 & 0x3F) << 12) | 
1169                                  ((c2 & 0x3F) << 6) |
1170                                   (c3 & 0x3F);
1171                     if (code_point < 65536 && code_point > 1114111) {
1172                         return false;
1173                     }
1174                     assert(code_point >= 65536 && code_point <= 1114111);
1175                     p += 4;
1176                 } else {
1177                     // Skip invalid or restricted encodings.
1178                     // Stop processing the UTF byte sequence early.
1179                     return false;
1180                 }
1181             }
1182         }
1183     }
1184     utf_string = p;
1185     return true;
1186 }
1187
1188 // See RFC-2781 "UTF-16, a transformation format of ISO 10646"
1189 // http://rfc-ref.org/RFC-TEXTS/2781/index.html
1190 // http://www.rfc-editor.org/rfc/rfc2781.txt
1191 static bool
1192 __glPathGetCodePointUTF16(const void *&utf_string,
1193                           GLuint &code_point)
1194 {
1195     // Section 2.2 (Decoding UTF-16) of http://www.rfc-editor.org/rfc/rfc2781.txt
1196     // "Decoding of a single character from UTF-16 to an ISO 10646 character
1197     // value proceeds as follows."
1198     const GLushort *p = reinterpret_cast<const GLushort*>(utf_string);
1199
1200     // "Let W1 be the next 16-bit integer in the
1201     // sequence of integers representing the text."
1202     GLushort W1 = p[0];
1203     // "1) If W1 < 0xD800 or W1 > 0xDFFF, the character value U is the value
1204     // of W1. Terminate."
1205     if ((W1 < 0xDB00) || (W1 > 0xDFFF)) {
1206         code_point = W1;
1207         p += 1;
1208     } else {
1209         // "2) Determine if W1 is between 0xD800 and 0xDBFF."
1210         bool between1 = (W1 >= 0xDB00) && (W1 <= 0xDBFF);
1211         if (!between1) {
1212             // "If not, the sequence
1213             // is in error and no valid character can be obtained using W1.
1214             // Terminate."
1215             return false;
1216         }
1217         // "Let W2 be the (eventual) next integer following W1."
1218         GLushort W2 = p[1];
1219         // DOES NOT APPLY because API provides character (not byte) count.
1220         // "3) If there is no W2 (that is, the sequence ends with W1), [Terminate]"
1221
1222         // "... or if W2 is not between 0xDC00 and 0xDFFF, the sequence
1223         // is in error.  Terminate."
1224         bool between2 = (W2 >= 0xDC00) && (W2 <= 0xDFFF);
1225         if (!between2) {
1226             return false;
1227         }
1228         // "4) Construct a 20-bit unsigned integer U', taking the 10 low-order
1229         // bits of W1 as its 10 high-order bits and the 10 low-order bits of
1230         // W2 as its 10 low-order bits."
1231         code_point = ((W1 & 0x3FF) << 10) |
1232                       (W2 & 0x3FF);
1233         // "5) Add 0x10000 to U' to obtain the character value U. Terminate."
1234         code_point += 0x10000;
1235         p += 2;
1236     }
1237     utf_string = p;
1238     return true;
1239 }
1240
1241 static size_t bytesOfSequence(GLsizei count, GLenum type, const GLvoid *sequence)
1242 {
1243     GLsizei bytes_per_element;
1244     switch (type) {
1245     case GL_BYTE:
1246         bytes_per_element = sizeof(GLbyte);
1247         break;
1248     case GL_UNSIGNED_BYTE:
1249         bytes_per_element = sizeof(GLubyte);
1250         break;
1251     case GL_SHORT:
1252         bytes_per_element = sizeof(GLshort);
1253         break;
1254     case GL_UNSIGNED_SHORT:
1255         bytes_per_element = sizeof(GLushort);
1256         break;
1257     case GL_INT:
1258         bytes_per_element = sizeof(GLint);
1259         break;
1260     case GL_UNSIGNED_INT:
1261         bytes_per_element = sizeof(GLuint);
1262         break;
1263     case GL_FLOAT:
1264         bytes_per_element = sizeof(GLfloat);
1265         break;
1266     case GL_2_BYTES:
1267         bytes_per_element = 2*sizeof(GLubyte);
1268         break;
1269     case GL_3_BYTES:
1270         bytes_per_element = 3*sizeof(GLubyte);
1271         break;
1272     case GL_4_BYTES:
1273         bytes_per_element = 4*sizeof(GLubyte);
1274         break;
1275     case GL_UTF8_NV:
1276         {
1277             const void *utf_string = sequence;
1278             for (GLsizei i=0; i<count; i++) {
1279                 GLuint code_point;  // ignored
1280                 bool ok = __glPathGetCodePointUTF8(utf_string, code_point);
1281                 if (!ok) {
1282                     break;
1283                 }
1284             }
1285             const char *start = reinterpret_cast<const char*>(sequence);
1286             const char *end = reinterpret_cast<const char*>(utf_string);
1287             return end - start;
1288         }
1289     case GL_UTF16_NV:
1290         {
1291             const void *utf_string = sequence;
1292             for (GLsizei i=0; i<count; i++) {
1293                 GLuint code_point;  // ignored
1294                 bool ok = __glPathGetCodePointUTF16(utf_string, code_point);
1295                 if (!ok) {
1296                     break;
1297                 }
1298             }
1299             const char *start = reinterpret_cast<const char*>(sequence);
1300             const char *end = reinterpret_cast<const char*>(utf_string);
1301             return end - start;
1302         }
1303     default:  // generate INVALID_ENUM
1304         return 0;
1305     }
1306     if (count > 0) {
1307         return count * bytes_per_element;
1308     } else {
1309         return 0;
1310     }
1311 }
1312
1313 static inline size_t
1314 _gl_Paths_size(GLsizei numPaths, GLenum pathNameType, const GLvoid *paths)
1315 {
1316     return bytesOfSequence(numPaths, pathNameType, paths);
1317 }
1318
1319 static inline size_t
1320 _gl_PathColorGen_size(GLenum genMode, GLenum colorFormat)
1321 {
1322     GLsizei coeffsPerComponent;
1323     switch (genMode) {
1324     case GL_NONE:
1325         coeffsPerComponent = 0;
1326         break;
1327     case GL_OBJECT_LINEAR:
1328     case GL_PATH_OBJECT_BOUNDING_BOX_NV:
1329         coeffsPerComponent = 3;
1330         break;
1331     case GL_EYE_LINEAR:
1332         coeffsPerComponent = 4;
1333         break;
1334     default:
1335         return 0;
1336     }
1337
1338     GLsizei components;
1339     switch (colorFormat) {
1340     case GL_LUMINANCE:
1341     case GL_ALPHA:
1342     case GL_INTENSITY:
1343         components = 1;
1344         break;
1345     case GL_LUMINANCE_ALPHA:
1346         components = 2;
1347         break;
1348     case GL_RGB:
1349         components = 3;
1350         break;
1351     case GL_RGBA:
1352         components = 4;
1353         break;
1354     default:
1355         return 0;
1356     }
1357
1358     GLsizei numCoeffs = components * coeffsPerComponent;
1359     return numCoeffs*sizeof(GLfloat);
1360 }
1361
1362 static inline size_t
1363 _gl_PathTexGen_size(GLenum genMode, GLsizei components)
1364 {
1365     GLsizei coeffsPerComponent;
1366     switch (genMode) {
1367     case GL_NONE:
1368         return 0;
1369     case GL_OBJECT_LINEAR:
1370     case GL_PATH_OBJECT_BOUNDING_BOX_NV:
1371         coeffsPerComponent = 3;
1372         break;
1373     case GL_EYE_LINEAR:
1374         coeffsPerComponent = 4;
1375         break;
1376     default:
1377         return 0;
1378     }
1379
1380     if (components < 1 || components > 4) {
1381         return 0;
1382     }
1383
1384     GLsizei numCoeffs = components * coeffsPerComponent;
1385     return numCoeffs*sizeof(GLfloat);
1386 }
1387
1388 static size_t valuesPerGetPathParameter(GLenum pname)
1389 {
1390     switch (pname) {
1391     case GL_PATH_FILL_MODE_NV:
1392     case GL_PATH_FILL_MASK_NV:
1393     case GL_PATH_FILL_COVER_MODE_NV:
1394     case GL_PATH_STROKE_WIDTH_NV:
1395     case GL_PATH_INITIAL_END_CAP_NV:
1396     case GL_PATH_TERMINAL_END_CAP_NV:
1397     case GL_PATH_JOIN_STYLE_NV:
1398     case GL_PATH_MITER_LIMIT_NV:
1399     case GL_PATH_INITIAL_DASH_CAP_NV:
1400     case GL_PATH_TERMINAL_DASH_CAP_NV:
1401     case GL_PATH_DASH_OFFSET_NV:
1402     case GL_PATH_DASH_OFFSET_RESET_NV:
1403     case GL_PATH_CLIENT_LENGTH_NV:
1404     case GL_PATH_STROKE_COVER_MODE_NV:
1405     case GL_PATH_STROKE_MASK_NV:
1406     case GL_PATH_STROKE_OVERSAMPLE_COUNT_NV:
1407     case GL_PATH_SAMPLE_QUALITY_NV:
1408         return 1;
1409     default:
1410         return 0;
1411     }
1412 }
1413
1414 static inline size_t
1415 _gl_GetPathParameter_size(GLenum pname)
1416 {
1417     return valuesPerGetPathParameter(pname);
1418 }
1419
1420 static inline size_t
1421 _gl_GetPathSpacing(GLsizei numPaths, GLenum transformType)
1422 {
1423     switch (transformType) {
1424     case GL_TRANSLATE_X_NV:
1425         return (numPaths-1)*1;
1426     case GL_TRANSLATE_2D_NV:
1427         return (numPaths-1)*2;
1428     default:
1429         return 0;
1430     }
1431 }
1432
1433 /**
1434  * Helper function for determining the string lengths for glShaderSource and
1435  * glShaderSourceARB, which is a tad too complex to inline in the specs.
1436  */
1437 template<class Char>
1438 static inline size_t
1439 _glShaderSource_length(const Char * const * string, const GLint *length, GLsizei index)
1440 {
1441     if (length != NULL && length[index] >= 0) {
1442         return (size_t)length[index];
1443     } else {
1444         return strlen(string[index]);
1445     }
1446 }
1447
1448 /**
1449  * Helper function for determining the string lengths for glGetDebugMessageLog*.
1450  */
1451 template<class Char>
1452 static inline size_t
1453 _glGetDebugMessageLog_length(const Char * string, const GLsizei *lengths, GLuint count)
1454 {
1455     size_t size = 0;
1456     GLuint index;
1457     if (lengths) {
1458         for (index = 0; index < count; ++index) {
1459             size += lengths[index];
1460         }
1461     } else {
1462         for (index = 0; index < count; ++index) {
1463             size += strlen(&string[size]) + 1;
1464         }
1465     }
1466     if (size) {
1467         // Remove the last null terminator
1468         --size;
1469     }
1470     return size;
1471 }
1472
1473 /* 
1474  * attribute list, terminated by the given terminator.
1475  */
1476 template<class T>
1477 static inline size_t
1478 _AttribList_size(const T *pAttribList, const T terminator = static_cast<T>(0))
1479 {
1480     size_t size = 0;
1481
1482     if (pAttribList) {
1483         do {
1484             ++size;
1485         } while (*pAttribList++ != terminator);
1486     }
1487
1488     return size;
1489 }
1490
1491
1492 /*
1493  * (key, value) attribute list, terminated by the given terminator.
1494  */
1495 template<class T>
1496 static inline size_t
1497 _AttribPairList_size(const T *pAttribList, const T terminator = static_cast<T>(0))
1498 {
1499     size_t size = 0;
1500
1501     if (pAttribList) {
1502         while (pAttribList[size] != terminator) {
1503             size += 2;
1504         }
1505         // terminator also counts
1506         ++size;
1507     }
1508
1509     return size;
1510 }
1511
1512
1513 #endif /* _GL_SIZE_HPP_ */