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