]> git.cworth.org Git - apitrace/blob - glsize.hpp
d81cdf1fe6071db14ac6853b6d4a3a5fa3405d62
[apitrace] / 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
40 #include "os.hpp"
41 #include "glimports.hpp"
42
43
44 static inline size_t
45 __gl_type_size(GLenum type)
46 {
47     switch (type) {
48     case GL_BOOL:
49     case GL_BYTE:
50     case GL_UNSIGNED_BYTE:
51         return 1;
52     case GL_SHORT:
53     case GL_UNSIGNED_SHORT:
54     case GL_2_BYTES:
55     case GL_HALF_FLOAT:
56         return 2;
57     case GL_3_BYTES:
58         return 3;
59     case GL_INT:
60     case GL_UNSIGNED_INT:
61     case GL_FLOAT:
62     case GL_4_BYTES:
63     case GL_FIXED:
64         return 4;
65     case GL_DOUBLE:
66         return 8;
67     default:
68         os::log("apitrace: warning: %s: unknown GLenum 0x%04X\n", __FUNCTION__, type);
69         return 0;
70     }
71 }
72
73 static inline void
74 __gl_uniform_size(GLenum type, GLenum &elemType, GLint &numElems) {
75     switch (type) {
76     case GL_FLOAT:
77         elemType = GL_FLOAT;
78         numElems = 1;
79         break;
80     case GL_FLOAT_VEC2:
81         elemType = GL_FLOAT;
82         numElems = 2;
83         break;
84     case GL_FLOAT_VEC3:
85         elemType = GL_FLOAT;
86         numElems = 3;
87         break;
88     case GL_FLOAT_VEC4:
89         elemType = GL_FLOAT;
90         numElems = 4;
91         break;
92     case GL_DOUBLE:
93         elemType = GL_DOUBLE;
94         numElems = 1;
95         break;
96     case GL_DOUBLE_VEC2:
97         elemType = GL_DOUBLE;
98         numElems = 2;
99         break;
100     case GL_DOUBLE_VEC3:
101         elemType = GL_DOUBLE;
102         numElems = 3;
103         break;
104     case GL_DOUBLE_VEC4:
105         elemType = GL_DOUBLE;
106         numElems = 4;
107         break;
108     case GL_INT:
109         elemType = GL_INT;
110         numElems = 1;
111         break;
112     case GL_INT_VEC2:
113         elemType = GL_INT;
114         numElems = 2;
115         break;
116     case GL_INT_VEC3:
117         elemType = GL_INT;
118         numElems = 3;
119         break;
120     case GL_INT_VEC4:
121         elemType = GL_INT;
122         numElems = 4;
123         break;
124     case GL_UNSIGNED_INT:
125         elemType = GL_UNSIGNED_INT;
126         numElems = 1;
127         break;
128     case GL_UNSIGNED_INT_VEC2:
129         elemType = GL_UNSIGNED_INT;
130         numElems = 2;
131         break;
132     case GL_UNSIGNED_INT_VEC3:
133         elemType = GL_UNSIGNED_INT;
134         numElems = 3;
135         break;
136     case GL_UNSIGNED_INT_VEC4:
137         elemType = GL_UNSIGNED_INT;
138         numElems = 4;
139         break;
140     case GL_BOOL:
141         elemType = GL_BOOL;
142         numElems = 1;
143         break;
144     case GL_BOOL_VEC2:
145         elemType = GL_BOOL;
146         numElems = 2;
147         break;
148     case GL_BOOL_VEC3:
149         elemType = GL_BOOL;
150         numElems = 3;
151         break;
152     case GL_BOOL_VEC4:
153         elemType = GL_BOOL;
154         numElems = 4;
155         break;
156     case GL_FLOAT_MAT2:
157         elemType = GL_FLOAT;
158         numElems = 2*2;
159         break;
160     case GL_FLOAT_MAT3:
161         elemType = GL_FLOAT;
162         numElems = 3*3;
163         break;
164     case GL_FLOAT_MAT4:
165         elemType = GL_FLOAT;
166         numElems = 4*4;
167         break;
168     case GL_FLOAT_MAT2x3:
169         elemType = GL_FLOAT;
170         numElems = 2*3;
171         break;
172     case GL_FLOAT_MAT2x4:
173         elemType = GL_FLOAT;
174         numElems = 2*4;
175         break;
176     case GL_FLOAT_MAT3x2:
177         elemType = GL_FLOAT;
178         numElems = 3*2;
179         break;
180     case GL_FLOAT_MAT3x4:
181         elemType = GL_FLOAT;
182         numElems = 3*4;
183         break;
184     case GL_FLOAT_MAT4x2:
185         elemType = GL_FLOAT;
186         numElems = 4*2;
187         break;
188     case GL_FLOAT_MAT4x3:
189         elemType = GL_FLOAT;
190         numElems = 4*3;
191         break;
192     case GL_DOUBLE_MAT2:
193         elemType = GL_DOUBLE;
194         numElems = 2*2;
195         break;
196     case GL_DOUBLE_MAT3:
197         elemType = GL_DOUBLE;
198         numElems = 3*3;
199         break;
200     case GL_DOUBLE_MAT4:
201         elemType = GL_DOUBLE;
202         numElems = 4*4;
203         break;
204     case GL_DOUBLE_MAT2x3:
205         elemType = GL_DOUBLE;
206         numElems = 2*3;
207         break;
208     case GL_DOUBLE_MAT2x4:
209         elemType = GL_DOUBLE;
210         numElems = 2*4;
211         break;
212     case GL_DOUBLE_MAT3x2:
213         elemType = GL_DOUBLE;
214         numElems = 3*2;
215         break;
216     case GL_DOUBLE_MAT3x4:
217         elemType = GL_DOUBLE;
218         numElems = 3*4;
219         break;
220     case GL_DOUBLE_MAT4x2:
221         elemType = GL_DOUBLE;
222         numElems = 4*2;
223         break;
224     case GL_DOUBLE_MAT4x3:
225         elemType = GL_DOUBLE;
226         numElems = 4*3;
227         break;
228     case GL_SAMPLER_1D:
229     case GL_SAMPLER_2D:
230     case GL_SAMPLER_3D:
231     case GL_SAMPLER_CUBE:
232     case GL_SAMPLER_1D_SHADOW:
233     case GL_SAMPLER_2D_SHADOW:
234     case GL_SAMPLER_1D_ARRAY:
235     case GL_SAMPLER_2D_ARRAY:
236     case GL_SAMPLER_CUBE_MAP_ARRAY:
237     case GL_SAMPLER_1D_ARRAY_SHADOW:
238     case GL_SAMPLER_2D_ARRAY_SHADOW:
239     case GL_SAMPLER_2D_MULTISAMPLE:
240     case GL_SAMPLER_2D_MULTISAMPLE_ARRAY:
241     case GL_SAMPLER_CUBE_SHADOW:
242     case GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW:
243     case GL_SAMPLER_BUFFER:
244     case GL_SAMPLER_2D_RECT:
245     case GL_SAMPLER_2D_RECT_SHADOW:
246     case GL_INT_SAMPLER_1D:
247     case GL_INT_SAMPLER_2D:
248     case GL_INT_SAMPLER_3D:
249     case GL_INT_SAMPLER_CUBE:
250     case GL_INT_SAMPLER_1D_ARRAY:
251     case GL_INT_SAMPLER_2D_ARRAY:
252     case GL_INT_SAMPLER_CUBE_MAP_ARRAY:
253     case GL_INT_SAMPLER_2D_MULTISAMPLE:
254     case GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY:
255     case GL_INT_SAMPLER_BUFFER:
256     case GL_INT_SAMPLER_2D_RECT:
257     case GL_UNSIGNED_INT_SAMPLER_1D:
258     case GL_UNSIGNED_INT_SAMPLER_2D:
259     case GL_UNSIGNED_INT_SAMPLER_3D:
260     case GL_UNSIGNED_INT_SAMPLER_CUBE:
261     case GL_UNSIGNED_INT_SAMPLER_1D_ARRAY:
262     case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY:
263     case GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY:
264     case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE:
265     case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY:
266     case GL_UNSIGNED_INT_SAMPLER_BUFFER:
267     case GL_UNSIGNED_INT_SAMPLER_2D_RECT:
268         elemType = GL_INT;
269         numElems = 1;
270         break;
271     default:
272         os::log("apitrace: warning: %s: unknown GLenum 0x%04X\n", __FUNCTION__, type);
273         elemType = GL_NONE;
274         numElems = 0;
275         return;
276     }
277 }
278     
279 static inline size_t
280 __glArrayPointer_size(GLint size, GLenum type, GLsizei stride, GLsizei maxIndex)
281 {
282     size_t elementSize = size*__gl_type_size(type);
283     if (!stride) {
284         stride = (GLsizei)elementSize;
285     }
286     return stride*maxIndex + elementSize;
287 }
288
289 #define __glVertexPointer_size(size, type, stride, maxIndex) __glArrayPointer_size(size, type, stride, maxIndex)
290 #define __glNormalPointer_size(type, stride, maxIndex) __glArrayPointer_size(3, type, stride, maxIndex)
291 #define __glColorPointer_size(size, type, stride, maxIndex) __glArrayPointer_size(size, type, stride, maxIndex)
292 #define __glIndexPointer_size(type, stride, maxIndex) __glArrayPointer_size(1, type, stride, maxIndex)
293 #define __glTexCoordPointer_size(size, type, stride, maxIndex) __glArrayPointer_size(size, type, stride, maxIndex)
294 #define __glEdgeFlagPointer_size(stride, maxIndex) __glArrayPointer_size(1, GL_BOOL, stride, maxIndex)
295 #define __glFogCoordPointer_size(type, stride, maxIndex) __glArrayPointer_size(1, type, stride, maxIndex)
296 #define __glSecondaryColorPointer_size(size, type, stride, maxIndex) __glArrayPointer_size(size, type, stride, maxIndex)
297 #define __glVertexAttribPointer_size(size, type, normalized, stride, maxIndex) __glArrayPointer_size(size, type, stride, maxIndex)
298 #define __glVertexAttribPointerARB_size(size, type, normalized, stride, maxIndex) __glArrayPointer_size(size, type, stride, maxIndex)
299 #define __glVertexAttribPointerNV_size(size, type, stride, maxIndex) __glArrayPointer_size(size, type, stride, maxIndex)
300
301 static inline GLuint
302 __glDrawArrays_maxindex(GLint first, GLsizei count)
303 {
304     if (!count) {
305         return 0;
306     }
307     return first + count - 1;
308 }
309
310 #define __glDrawArraysEXT_maxindex __glDrawArrays_maxindex
311
312 static inline GLuint
313 __glDrawElementsBaseVertex_maxindex(GLsizei count, GLenum type, const GLvoid *indices, GLint basevertex)
314 {
315     GLvoid *temp = 0;
316     GLint __element_array_buffer = 0;
317
318     if (!count) {
319         return 0;
320     }
321
322     __glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &__element_array_buffer);
323     if (__element_array_buffer) {
324         // Read indices from index buffer object
325         GLintptr offset = (GLintptr)indices;
326         GLsizeiptr size = count*__gl_type_size(type);
327         GLvoid *temp = malloc(size);
328         if (!temp) {
329             return 0;
330         }
331         memset(temp, 0, size);
332         __glGetBufferSubData(GL_ELEMENT_ARRAY_BUFFER, offset, size, temp);
333         indices = temp;
334     } else {
335         if (!indices) {
336             return 0;
337         }
338     }
339
340     GLuint maxindex = 0;
341     GLsizei i;
342     if (type == GL_UNSIGNED_BYTE) {
343         const GLubyte *p = (const GLubyte *)indices;
344         for (i = 0; i < count; ++i) {
345             if (p[i] > maxindex) {
346                 maxindex = p[i];
347             }
348         }
349     } else if (type == GL_UNSIGNED_SHORT) {
350         const GLushort *p = (const GLushort *)indices;
351         for (i = 0; i < count; ++i) {
352             if (p[i] > maxindex) {
353                 maxindex = p[i];
354             }
355         }
356     } else if (type == GL_UNSIGNED_INT) {
357         const GLuint *p = (const GLuint *)indices;
358         for (i = 0; i < count; ++i) {
359             if (p[i] > maxindex) {
360                 maxindex = p[i];
361             }
362         }
363     } else {
364         os::log("apitrace: warning: %s: unknown GLenum 0x%04X\n", __FUNCTION__, type);
365     }
366
367     if (__element_array_buffer) {
368         free(temp);
369     }
370
371     maxindex += basevertex;
372
373     return maxindex;
374 }
375
376 #define __glDrawRangeElementsBaseVertex_maxindex(start, end, count, type, indices, basevertex) __glDrawElementsBaseVertex_maxindex(count, type, indices, basevertex)
377
378 #define __glDrawElements_maxindex(count, type, indices) __glDrawElementsBaseVertex_maxindex(count, type, indices, 0);
379 #define __glDrawRangeElements_maxindex(start, end, count, type, indices) __glDrawElements_maxindex(count, type, indices)
380 #define __glDrawRangeElementsEXT_maxindex __glDrawRangeElements_maxindex
381
382 /* FIXME take in consideration instancing */
383 #define __glDrawArraysInstanced_maxindex(first, count, primcount) __glDrawArrays_maxindex(first, count)
384 #define __glDrawElementsInstanced_maxindex(count, type, indices, primcount) __glDrawElements_maxindex(count, type, indices)
385 #define __glDrawElementsInstancedBaseVertex_maxindex(count, type, indices, primcount, basevertex) __glDrawElementsBaseVertex_maxindex(count, type, indices, basevertex)
386 #define __glDrawRangeElementsInstanced_maxindex(start, end, count, type, indices, primcount) __glDrawRangeElements_maxindex(start, end, count, type, indices)
387 #define __glDrawRangeElementsInstancedBaseVertex_maxindex(start, end, count, type, indices, primcount, basevertex) __glDrawRangeElementsBaseVertex_maxindex(start, end, count, type, indices, basevertex)
388
389 #define __glDrawArraysInstancedBaseInstance_maxindex(first, count, primcount, baseinstance) __glDrawArrays_maxindex(first, count)
390 #define __glDrawElementsInstancedBaseInstance_maxindex(count, type, indices, primcount, baseinstance) __glDrawElements_maxindex(count, type, indices)
391 #define __glDrawElementsInstancedBaseVertexBaseInstance_maxindex(count, type, indices, primcount, basevertex, baseinstance) __glDrawElementsBaseVertex_maxindex(count, type, indices, basevertex)
392
393 #define __glDrawArraysInstancedARB_maxindex __glDrawArraysInstanced_maxindex
394 #define __glDrawElementsInstancedARB_maxindex __glDrawElementsInstanced_maxindex
395 #define __glDrawArraysInstancedEXT_maxindex __glDrawArraysInstanced_maxindex
396 #define __glDrawElementsInstancedEXT_maxindex __glDrawElementsInstanced_maxindex
397
398 static inline GLuint
399 __glDrawArraysIndirect_maxindex(const GLvoid *indirect) {
400     os::log("apitrace: warning: %s: unsupported\n", __FUNCTION__);
401     return 0;
402 }
403
404 static inline GLuint
405 __glDrawElementsIndirect_maxindex(GLenum type, const GLvoid *indirect) {
406     os::log("apitrace: warning: %s: unsupported\n", __FUNCTION__);
407     return 0;
408 }
409
410 static inline GLuint
411 __glMultiDrawArrays_maxindex(const GLint *first, const GLsizei *count, GLsizei primcount) {
412     GLuint maxindex = 0;
413     for (GLsizei prim = 0; prim < primcount; ++prim) {
414         GLuint maxindex_prim = __glDrawArrays_maxindex(first[prim], count[prim]);
415         maxindex = std::max(maxindex, maxindex_prim);
416     }
417     return maxindex;
418 }
419
420 static inline GLuint
421 __glMultiDrawElements_maxindex(const GLsizei *count, GLenum type, const GLvoid* *indices, GLsizei primcount) {
422     GLuint maxindex = 0;
423     for (GLsizei prim = 0; prim < primcount; ++prim) {
424         GLuint maxindex_prim = __glDrawElements_maxindex(count[prim], type, indices[prim]);
425         maxindex = std::max(maxindex, maxindex_prim);
426     }
427     return maxindex;
428 }
429
430 static inline GLuint
431 __glMultiDrawElementsBaseVertex_maxindex(const GLsizei *count, GLenum type, const GLvoid* *indices, GLsizei primcount, const GLint * basevertex) {
432     GLuint maxindex = 0;
433     for (GLsizei prim = 0; prim < primcount; ++prim) {
434         GLuint maxindex_prim = __glDrawElementsBaseVertex_maxindex(count[prim], type, indices[prim], basevertex[prim]);
435         maxindex = std::max(maxindex, maxindex_prim);
436     }
437     return maxindex;
438 }
439
440 #define __glMultiDrawArraysEXT_maxindex __glMultiDrawArrays_maxindex
441 #define __glMultiDrawElementsEXT_maxindex __glMultiDrawElements_maxindex
442
443 #define __glMultiModeDrawArraysIBM_maxindex(first, count, primcount, modestride) __glMultiDrawArrays_maxindex(first, count, primcount)
444 #define __glMultiModeDrawElementsIBM_maxindex(count, type, indices, primcount, modestride) __glMultiDrawElements_maxindex(count, type, (const GLvoid **)indices, primcount)
445
446
447 static inline size_t
448 __glCallLists_size(GLsizei n, GLenum type)
449 {
450     return n*__gl_type_size(type);
451 }
452
453 static inline size_t
454 __glMap1d_size(GLenum target, GLint stride, GLint order)
455 {
456     if (order < 1) {
457         return 0;
458     }
459
460     GLint channels;
461     switch (target) {
462     case GL_MAP1_INDEX:
463     case GL_MAP1_TEXTURE_COORD_1:
464         channels = 1;
465         break;
466     case GL_MAP1_TEXTURE_COORD_2:
467         channels = 2;
468         break;
469     case GL_MAP1_NORMAL:
470     case GL_MAP1_TEXTURE_COORD_3:
471     case GL_MAP1_VERTEX_3:
472         channels = 3;
473         break;
474     case GL_MAP1_COLOR_4:
475     case GL_MAP1_TEXTURE_COORD_4:
476     case GL_MAP1_VERTEX_4:
477         channels = 4;
478         break;
479     default:
480         os::log("apitrace: warning: %s: unknown GLenum 0x%04X\n", __FUNCTION__, target);
481         return 0;
482     }
483
484     if (stride < channels) {
485         return 0;
486     }
487
488     return channels + stride * (order - 1);
489 }
490
491 #define __glMap1f_size __glMap1d_size
492
493 static inline size_t
494 __glMap2d_size(GLenum target, GLint ustride, GLint uorder, GLint vstride, GLint vorder)
495 {
496     if (uorder < 1 || vorder < 1) {
497         return 0;
498     }
499
500     GLint channels;
501     switch (target) {
502     case GL_MAP2_INDEX:
503     case GL_MAP2_TEXTURE_COORD_1:
504         channels = 1;
505         break;
506     case GL_MAP2_TEXTURE_COORD_2:
507         channels = 2;
508         break;
509     case GL_MAP2_NORMAL:
510     case GL_MAP2_TEXTURE_COORD_3:
511     case GL_MAP2_VERTEX_3:
512         channels = 3;
513         break;
514     case GL_MAP2_COLOR_4:
515     case GL_MAP2_TEXTURE_COORD_4:
516     case GL_MAP2_VERTEX_4:
517         channels = 4;
518         break;
519     default:
520         os::log("apitrace: warning: %s: unknown GLenum 0x%04X\n", __FUNCTION__, target);
521         return 0;
522     }
523
524     if (ustride < channels || vstride < channels) {
525         return 0;
526     }
527
528     return channels + 
529            ustride * (uorder - 1) +
530            vstride * (vorder - 1);
531 }
532
533 #define __glMap2f_size __glMap2d_size
534
535 static inline unsigned
536 __gl_format_channels(GLenum format) {
537     switch (format) {
538     case GL_COLOR_INDEX:
539     case GL_RED:
540     case GL_GREEN:
541     case GL_BLUE:
542     case GL_ALPHA:
543     case GL_INTENSITY:
544     case GL_LUMINANCE:
545     case GL_DEPTH_COMPONENT:
546     case GL_STENCIL_INDEX:
547         return 1;
548     case GL_DEPTH_STENCIL:
549     case GL_LUMINANCE_ALPHA:
550     case GL_RG:
551     case GL_HILO_NV:
552     case GL_DSDT_NV:
553         return 2;
554     case GL_RGB:
555     case GL_BGR:
556     case GL_DSDT_MAG_NV:
557         return 3;
558     case GL_RGBA:
559     case GL_BGRA:
560     case GL_ABGR_EXT:
561     case GL_CMYK_EXT:
562     case GL_DSDT_MAG_VIB_NV:
563         return 4;
564     case GL_CMYKA_EXT:
565         return 5;
566     default:
567         os::log("apitrace: warning: %s: unexpected format GLenum 0x%04X\n", __FUNCTION__, format);
568         return 0;
569     }
570 }
571
572 template<class X>
573 static inline bool
574 _is_pot(X x) {
575     return (x & (x - 1)) == 0;
576 }
577
578 template<class X, class Y>
579 static inline X
580 _align(X x, Y y) {
581     return (x + (y - 1)) & ~(y - 1);
582 }
583
584 static inline size_t
585 __gl_image_size(GLenum format, GLenum type, GLsizei width, GLsizei height, GLsizei depth, GLboolean has_unpack_subimage) {
586     unsigned num_channels = __gl_format_channels(format);
587
588     unsigned bits_per_pixel;
589     switch (type) {
590     case GL_BITMAP:
591         bits_per_pixel = 1;
592         break;
593     case GL_BYTE:
594     case GL_UNSIGNED_BYTE:
595         bits_per_pixel = 8 * num_channels;
596         break;
597     case GL_SHORT:
598     case GL_UNSIGNED_SHORT:
599     case GL_HALF_FLOAT:
600         bits_per_pixel = 16 * num_channels;
601         break;
602     case GL_INT:
603     case GL_UNSIGNED_INT:
604     case GL_FLOAT:
605         bits_per_pixel = 32 * num_channels;
606         break;
607     case GL_UNSIGNED_BYTE_3_3_2:
608     case GL_UNSIGNED_BYTE_2_3_3_REV:
609         bits_per_pixel = 8;
610         break;
611     case GL_UNSIGNED_SHORT_4_4_4_4:
612     case GL_UNSIGNED_SHORT_4_4_4_4_REV:
613     case GL_UNSIGNED_SHORT_5_5_5_1:
614     case GL_UNSIGNED_SHORT_1_5_5_5_REV:
615     case GL_UNSIGNED_SHORT_5_6_5:
616     case GL_UNSIGNED_SHORT_5_6_5_REV:
617     case GL_UNSIGNED_SHORT_8_8_MESA:
618     case GL_UNSIGNED_SHORT_8_8_REV_MESA:
619         bits_per_pixel = 16;
620         break;
621     case GL_UNSIGNED_INT_8_8_8_8:
622     case GL_UNSIGNED_INT_8_8_8_8_REV:
623     case GL_UNSIGNED_INT_10_10_10_2:
624     case GL_UNSIGNED_INT_2_10_10_10_REV:
625     case GL_UNSIGNED_INT_24_8:
626     case GL_UNSIGNED_INT_10F_11F_11F_REV:
627     case GL_UNSIGNED_INT_5_9_9_9_REV:
628     case GL_UNSIGNED_INT_S8_S8_8_8_NV:
629     case GL_UNSIGNED_INT_8_8_S8_S8_REV_NV:
630         bits_per_pixel = 32;
631         break;
632     case GL_FLOAT_32_UNSIGNED_INT_24_8_REV:
633         bits_per_pixel = 64;
634         break;
635     default:
636         os::log("apitrace: warning: %s: unexpected type GLenum 0x%04X\n", __FUNCTION__, type);
637         bits_per_pixel = 0;
638         break;
639     }
640
641     GLint alignment = 4;
642     GLint row_length = 0;
643     GLint image_height = 0;
644     GLint skip_rows = 0;
645     GLint skip_pixels = 0;
646     GLint skip_images = 0;
647
648     __glGetIntegerv(GL_UNPACK_ALIGNMENT, &alignment);
649     if (has_unpack_subimage) {
650         __glGetIntegerv(GL_UNPACK_ROW_LENGTH,   &row_length);
651         __glGetIntegerv(GL_UNPACK_IMAGE_HEIGHT, &image_height);
652         __glGetIntegerv(GL_UNPACK_SKIP_ROWS,    &skip_rows);
653         __glGetIntegerv(GL_UNPACK_SKIP_PIXELS,  &skip_pixels);
654         __glGetIntegerv(GL_UNPACK_SKIP_IMAGES,  &skip_images);
655     }
656
657     if (row_length <= 0) {
658         row_length = width;
659     }
660
661     size_t row_stride = (row_length*bits_per_pixel + 7)/8;
662
663     if ((GLint)bits_per_pixel < alignment*8 &&
664         (bits_per_pixel & 7) == 0 &&
665         _is_pot(bits_per_pixel)) {
666         row_stride = _align(row_stride, alignment);
667     }
668
669     if (image_height <= 0) {
670         image_height = height;
671     }
672
673     /* XXX: GL_UNPACK_IMAGE_HEIGHT and GL_UNPACK_SKIP_IMAGES should probably
674      * not be considered for pixel rectangles. */
675
676     size_t image_stride = image_height*row_stride;
677
678     size_t size = depth*image_stride;
679
680     size += (skip_pixels*bits_per_pixel + 7)/8;
681     size += skip_rows*row_stride;
682     size += skip_images*image_stride;
683
684     return size;
685 }
686
687 // note that can_unpack_subimage() is generated by gltrace.py
688 #define __glTexImage3D_size(format, type, width, height, depth) __gl_image_size(format, type, width, height, depth, can_unpack_subimage())
689 #define __glTexImage2D_size(format, type, width, height)        __gl_image_size(format, type, width, height, 1, can_unpack_subimage())
690 #define __glTexImage1D_size(format, type, width)                __gl_image_size(format, type, width, 1, 1, can_unpack_subimage())
691
692 #define __glTexSubImage3D_size(format, type, width, height, depth) __glTexImage3D_size(format, type, width, height, depth)
693 #define __glTexSubImage2D_size(format, type, width, height)        __glTexImage2D_size(format, type, width, height)
694 #define __glTexSubImage1D_size(format, type, width)                __glTexImage1D_size(format, type, width)
695
696 #define __glTexImage3DEXT_size __glTexImage3D_size
697 #define __glTexImage2DEXT_size __glTexImage2D_size
698 #define __glTexImage1DEXT_size __glTexImage1D_size
699 #define __glTexSubImage3DEXT_size __glTexSubImage3D_size
700 #define __glTexSubImage2DEXT_size __glTexSubImage2D_size
701 #define __glTexSubImage1DEXT_size __glTexSubImage1D_size
702
703 #define __glTextureImage3DEXT_size __glTexImage3D_size
704 #define __glTextureImage2DEXT_size __glTexImage2D_size
705 #define __glTextureImage1DEXT_size __glTexImage1D_size
706 #define __glTextureSubImage3DEXT_size __glTexSubImage3D_size
707 #define __glTextureSubImage2DEXT_size __glTexSubImage2D_size
708 #define __glTextureSubImage1DEXT_size __glTexSubImage1D_size
709
710 #define __glMultiTexImage3DEXT_size __glTexImage3D_size
711 #define __glMultiTexImage2DEXT_size __glTexImage2D_size
712 #define __glMultiTexImage1DEXT_size __glTexImage1D_size
713 #define __glMultiTexSubImage3DEXT_size __glTexSubImage3D_size
714 #define __glMultiTexSubImage2DEXT_size __glTexSubImage2D_size
715 #define __glMultiTexSubImage1DEXT_size __glTexSubImage1D_size
716
717 #define __glDrawPixels_size(format, type, width, height) __glTexImage2D_size(format, type, width, height)
718 #define __glConvolutionFilter1D_size(format, type, width) __glTexImage1D_size(format, type, width)
719 #define __glConvolutionFilter2D_size(format, type, width, height) __glTexImage2D_size(format, type, width, height)
720 #define __glColorTable_size(format, type, width) __glTexImage1D_size(format, type, width)
721 #define __glColorSubTable_size(format, type, count) __glColorTable_size(format, type, count)
722
723 #define __glBitmap_size(width, height) __glTexImage2D_size(GL_COLOR_INDEX, GL_BITMAP, width, height)
724 #define __glPolygonStipple_size() __glBitmap_size(32, 32)
725
726 static inline size_t
727 __glClearBuffer_size(GLenum buffer)
728 {
729     switch (buffer) {
730     case GL_COLOR:
731     case GL_FRONT:
732     case GL_BACK:
733     case GL_LEFT:
734     case GL_RIGHT:
735     case GL_FRONT_AND_BACK:
736         return 4;
737     case GL_DEPTH:
738     case GL_STENCIL:
739         return 1;
740     default:
741         os::log("apitrace: warning: %s: unexpected buffer GLenum 0x%04X\n", __FUNCTION__, buffer);
742         return 0;
743     }
744 }
745
746 /* 
747  * attribute list, terminated by the given terminator.
748  */
749 template<class T>
750 static inline size_t
751 __AttribList_size(const T *pAttribList, const T terminator = static_cast<T>(0))
752 {
753     size_t size = 0;
754
755     if (pAttribList) {
756         do {
757             ++size;
758         } while (*pAttribList++ != terminator);
759     }
760
761     return size;
762 }
763
764
765 /*
766  * (key, value) attribute list, terminated by the given terminator.
767  */
768 template<class T>
769 static inline size_t
770 __AttribPairList_size(const T *pAttribList, const T terminator = static_cast<T>(0))
771 {
772     size_t size = 0;
773
774     if (pAttribList) {
775         while (pAttribList[size] != terminator) {
776             size += 2;
777         }
778         // terminator also counts
779         ++size;
780     }
781
782     return size;
783 }
784
785
786 #endif /* _GL_SIZE_HPP_ */