glu/sgi: Fix memory leak in gluBuild1DMipmapLevelsCore.
[platform/upstream/mesa.git] / src / glu / sgi / libutil / mipmap.c
1 /*
2  * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
3  * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a
6  * copy of this software and associated documentation files (the "Software"),
7  * to deal in the Software without restriction, including without limitation
8  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9  * and/or sell copies of the Software, and to permit persons to whom the
10  * Software is furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice including the dates of first publication and
13  * either this permission notice or a reference to
14  * http://oss.sgi.com/projects/FreeB/
15  * shall be included in all copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20  * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
22  * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23  * SOFTWARE.
24  *
25  * Except as contained in this notice, the name of Silicon Graphics, Inc.
26  * shall not be used in advertising or otherwise to promote the sale, use or
27  * other dealings in this Software without prior written authorization from
28  * Silicon Graphics, Inc.
29  */
30
31 #include "gluos.h"
32 #include <assert.h>
33 #include <GL/glu.h>
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37 #include <limits.h>             /* UINT_MAX */
38 #include <math.h>
39 #include "gluint.h"
40
41 typedef union {
42     unsigned char ub[4];
43     unsigned short us[2];
44     unsigned int ui;
45     char b[4];
46     short s[2];
47     int i;
48     float f;
49 } Type_Widget;
50
51 /* Pixel storage modes */
52 typedef struct {
53    GLint pack_alignment;
54    GLint pack_row_length;
55    GLint pack_skip_rows;
56    GLint pack_skip_pixels;
57    GLint pack_lsb_first;
58    GLint pack_swap_bytes;
59    GLint pack_skip_images;
60    GLint pack_image_height;
61
62    GLint unpack_alignment;
63    GLint unpack_row_length;
64    GLint unpack_skip_rows;
65    GLint unpack_skip_pixels;
66    GLint unpack_lsb_first;
67    GLint unpack_swap_bytes;
68    GLint unpack_skip_images;
69    GLint unpack_image_height;
70 } PixelStorageModes;
71
72 static int gluBuild1DMipmapLevelsCore(GLenum, GLint,
73                                       GLsizei,
74                                       GLsizei,
75                                       GLenum, GLenum, GLint, GLint, GLint,
76                                       const void *);
77 static int gluBuild2DMipmapLevelsCore(GLenum, GLint,
78                                       GLsizei, GLsizei,
79                                       GLsizei, GLsizei,
80                                       GLenum, GLenum, GLint, GLint, GLint,
81                                       const void *);
82 static int gluBuild3DMipmapLevelsCore(GLenum, GLint,
83                                       GLsizei, GLsizei, GLsizei,
84                                       GLsizei, GLsizei, GLsizei,
85                                       GLenum, GLenum, GLint, GLint, GLint,
86                                       const void *);
87
88 /*
89  * internal function declarations
90  */
91 static GLfloat bytes_per_element(GLenum type);
92 static GLint elements_per_group(GLenum format, GLenum type);
93 static GLint is_index(GLenum format);
94 static GLint image_size(GLint width, GLint height, GLenum format, GLenum type);
95 static void fill_image(const PixelStorageModes *,
96                        GLint width, GLint height, GLenum format,
97                        GLenum type, GLboolean index_format,
98                        const void *userdata, GLushort *newimage);
99 static void empty_image(const PixelStorageModes *,
100                         GLint width, GLint height, GLenum format,
101                         GLenum type, GLboolean index_format,
102                         const GLushort *oldimage, void *userdata);
103 static void scale_internal(GLint components, GLint widthin, GLint heightin,
104                            const GLushort *datain,
105                            GLint widthout, GLint heightout,
106                            GLushort *dataout);
107
108 static void scale_internal_ubyte(GLint components, GLint widthin,
109                            GLint heightin, const GLubyte *datain,
110                            GLint widthout, GLint heightout,
111                            GLubyte *dataout, GLint element_size,
112                            GLint ysize, GLint group_size);
113 static void scale_internal_byte(GLint components, GLint widthin,
114                            GLint heightin, const GLbyte *datain,
115                            GLint widthout, GLint heightout,
116                            GLbyte *dataout, GLint element_size,
117                            GLint ysize, GLint group_size);
118 static void scale_internal_ushort(GLint components, GLint widthin,
119                            GLint heightin, const GLushort *datain,
120                            GLint widthout, GLint heightout,
121                            GLushort *dataout, GLint element_size,
122                            GLint ysize, GLint group_size,
123                            GLint myswap_bytes);
124 static void scale_internal_short(GLint components, GLint widthin,
125                            GLint heightin, const GLshort *datain,
126                            GLint widthout, GLint heightout,
127                            GLshort *dataout, GLint element_size,
128                            GLint ysize, GLint group_size,
129                            GLint myswap_bytes);
130 static void scale_internal_uint(GLint components, GLint widthin,
131                            GLint heightin, const GLuint *datain,
132                            GLint widthout, GLint heightout,
133                            GLuint *dataout, GLint element_size,
134                            GLint ysize, GLint group_size,
135                            GLint myswap_bytes);
136 static void scale_internal_int(GLint components, GLint widthin,
137                            GLint heightin, const GLint *datain,
138                            GLint widthout, GLint heightout,
139                            GLint *dataout, GLint element_size,
140                            GLint ysize, GLint group_size,
141                            GLint myswap_bytes);
142 static void scale_internal_float(GLint components, GLint widthin,
143                            GLint heightin, const GLfloat *datain,
144                            GLint widthout, GLint heightout,
145                            GLfloat *dataout, GLint element_size,
146                            GLint ysize, GLint group_size,
147                            GLint myswap_bytes);
148
149 static int checkMipmapArgs(GLenum, GLenum, GLenum);
150 static GLboolean legalFormat(GLenum);
151 static GLboolean legalType(GLenum);
152 static GLboolean isTypePackedPixel(GLenum);
153 static GLboolean isLegalFormatForPackedPixelType(GLenum, GLenum);
154 static GLboolean isLegalLevels(GLint, GLint, GLint, GLint);
155 static void closestFit(GLenum, GLint, GLint, GLint, GLenum, GLenum,
156                        GLint *, GLint *);
157
158 /* all extract/shove routines must return double to handle unsigned ints */
159 static GLdouble extractUbyte(int, const void *);
160 static void shoveUbyte(GLdouble, int, void *);
161 static GLdouble extractSbyte(int, const void *);
162 static void shoveSbyte(GLdouble, int, void *);
163 static GLdouble extractUshort(int, const void *);
164 static void shoveUshort(GLdouble, int, void *);
165 static GLdouble extractSshort(int, const void *);
166 static void shoveSshort(GLdouble, int, void *);
167 static GLdouble extractUint(int, const void *);
168 static void shoveUint(GLdouble, int, void *);
169 static GLdouble extractSint(int, const void *);
170 static void shoveSint(GLdouble, int, void *);
171 static GLdouble extractFloat(int, const void *);
172 static void shoveFloat(GLdouble, int, void *);
173 static void halveImageSlice(int, GLdouble (*)(int, const void *),
174                             void (*)(GLdouble, int, void *),
175                             GLint, GLint, GLint,
176                             const void *, void *,
177                             GLint, GLint, GLint, GLint, GLint);
178 static void halveImage3D(int, GLdouble (*)(int, const void *),
179                          void (*)(GLdouble, int, void *),
180                          GLint, GLint, GLint,
181                          const void *, void *,
182                          GLint, GLint, GLint, GLint, GLint);
183
184 /* packedpixel type scale routines */
185 static void extract332(int,const void *, GLfloat []);
186 static void shove332(const GLfloat [],int ,void *);
187 static void extract233rev(int,const void *, GLfloat []);
188 static void shove233rev(const GLfloat [],int ,void *);
189 static void extract565(int,const void *, GLfloat []);
190 static void shove565(const GLfloat [],int ,void *);
191 static void extract565rev(int,const void *, GLfloat []);
192 static void shove565rev(const GLfloat [],int ,void *);
193 static void extract4444(int,const void *, GLfloat []);
194 static void shove4444(const GLfloat [],int ,void *);
195 static void extract4444rev(int,const void *, GLfloat []);
196 static void shove4444rev(const GLfloat [],int ,void *);
197 static void extract5551(int,const void *, GLfloat []);
198 static void shove5551(const GLfloat [],int ,void *);
199 static void extract1555rev(int,const void *, GLfloat []);
200 static void shove1555rev(const GLfloat [],int ,void *);
201 static void extract8888(int,const void *, GLfloat []);
202 static void shove8888(const GLfloat [],int ,void *);
203 static void extract8888rev(int,const void *, GLfloat []);
204 static void shove8888rev(const GLfloat [],int ,void *);
205 static void extract1010102(int,const void *, GLfloat []);
206 static void shove1010102(const GLfloat [],int ,void *);
207 static void extract2101010rev(int,const void *, GLfloat []);
208 static void shove2101010rev(const GLfloat [],int ,void *);
209 static void scaleInternalPackedPixel(int,
210                                      void (*)(int, const void *,GLfloat []),
211                                      void (*)(const GLfloat [],int, void *),
212                                      GLint,GLint, const void *,
213                                      GLint,GLint,void *,GLint,GLint,GLint);
214 static void halveImagePackedPixel(int,
215                                   void (*)(int, const void *,GLfloat []),
216                                   void (*)(const GLfloat [],int, void *),
217                                   GLint, GLint, const void *,
218                                   void *, GLint, GLint, GLint);
219 static void halve1DimagePackedPixel(int,
220                                     void (*)(int, const void *,GLfloat []),
221                                     void (*)(const GLfloat [],int, void *),
222                                     GLint, GLint, const void *,
223                                     void *, GLint, GLint, GLint);
224
225 static void halve1Dimage_ubyte(GLint, GLuint, GLuint,const GLubyte *,
226                                GLubyte *, GLint, GLint, GLint);
227 static void halve1Dimage_byte(GLint, GLuint, GLuint,const GLbyte *, GLbyte *,
228                               GLint, GLint, GLint);
229 static void halve1Dimage_ushort(GLint, GLuint, GLuint, const GLushort *,
230                                 GLushort *, GLint, GLint, GLint, GLint);
231 static void halve1Dimage_short(GLint, GLuint, GLuint,const GLshort *, GLshort *,
232                                GLint, GLint, GLint, GLint);
233 static void halve1Dimage_uint(GLint, GLuint, GLuint, const GLuint *, GLuint *,
234                               GLint, GLint, GLint, GLint);
235 static void halve1Dimage_int(GLint, GLuint, GLuint, const GLint *, GLint *,
236                              GLint, GLint, GLint, GLint);
237 static void halve1Dimage_float(GLint, GLuint, GLuint, const GLfloat *, GLfloat *,
238                                GLint, GLint, GLint, GLint);
239
240 static GLint imageSize3D(GLint, GLint, GLint, GLenum,GLenum);
241 static void fillImage3D(const PixelStorageModes *, GLint, GLint, GLint,GLenum,
242                         GLenum, GLboolean, const void *, GLushort *);
243 static void emptyImage3D(const PixelStorageModes *,
244                          GLint, GLint, GLint, GLenum,
245                          GLenum, GLboolean,
246                          const GLushort *, void *);
247 static void scaleInternal3D(GLint, GLint, GLint, GLint, const GLushort *,
248                             GLint, GLint, GLint, GLushort *);
249
250 static void retrieveStoreModes(PixelStorageModes *psm)
251 {
252     glGetIntegerv(GL_UNPACK_ALIGNMENT, &psm->unpack_alignment);
253     glGetIntegerv(GL_UNPACK_ROW_LENGTH, &psm->unpack_row_length);
254     glGetIntegerv(GL_UNPACK_SKIP_ROWS, &psm->unpack_skip_rows);
255     glGetIntegerv(GL_UNPACK_SKIP_PIXELS, &psm->unpack_skip_pixels);
256     glGetIntegerv(GL_UNPACK_LSB_FIRST, &psm->unpack_lsb_first);
257     glGetIntegerv(GL_UNPACK_SWAP_BYTES, &psm->unpack_swap_bytes);
258
259     glGetIntegerv(GL_PACK_ALIGNMENT, &psm->pack_alignment);
260     glGetIntegerv(GL_PACK_ROW_LENGTH, &psm->pack_row_length);
261     glGetIntegerv(GL_PACK_SKIP_ROWS, &psm->pack_skip_rows);
262     glGetIntegerv(GL_PACK_SKIP_PIXELS, &psm->pack_skip_pixels);
263     glGetIntegerv(GL_PACK_LSB_FIRST, &psm->pack_lsb_first);
264     glGetIntegerv(GL_PACK_SWAP_BYTES, &psm->pack_swap_bytes);
265 }
266
267 static void retrieveStoreModes3D(PixelStorageModes *psm)
268 {
269     glGetIntegerv(GL_UNPACK_ALIGNMENT, &psm->unpack_alignment);
270     glGetIntegerv(GL_UNPACK_ROW_LENGTH, &psm->unpack_row_length);
271     glGetIntegerv(GL_UNPACK_SKIP_ROWS, &psm->unpack_skip_rows);
272     glGetIntegerv(GL_UNPACK_SKIP_PIXELS, &psm->unpack_skip_pixels);
273     glGetIntegerv(GL_UNPACK_LSB_FIRST, &psm->unpack_lsb_first);
274     glGetIntegerv(GL_UNPACK_SWAP_BYTES, &psm->unpack_swap_bytes);
275     glGetIntegerv(GL_UNPACK_SKIP_IMAGES, &psm->unpack_skip_images);
276     glGetIntegerv(GL_UNPACK_IMAGE_HEIGHT, &psm->unpack_image_height);
277
278     glGetIntegerv(GL_PACK_ALIGNMENT, &psm->pack_alignment);
279     glGetIntegerv(GL_PACK_ROW_LENGTH, &psm->pack_row_length);
280     glGetIntegerv(GL_PACK_SKIP_ROWS, &psm->pack_skip_rows);
281     glGetIntegerv(GL_PACK_SKIP_PIXELS, &psm->pack_skip_pixels);
282     glGetIntegerv(GL_PACK_LSB_FIRST, &psm->pack_lsb_first);
283     glGetIntegerv(GL_PACK_SWAP_BYTES, &psm->pack_swap_bytes);
284     glGetIntegerv(GL_PACK_SKIP_IMAGES, &psm->pack_skip_images);
285     glGetIntegerv(GL_PACK_IMAGE_HEIGHT, &psm->pack_image_height);
286 }
287
288 static int computeLog(GLuint value)
289 {
290     int i;
291
292     i = 0;
293
294     /* Error! */
295     if (value == 0) return -1;
296
297     for (;;) {
298         if (value & 1) {
299             /* Error ! */
300             if (value != 1) return -1;
301             return i;
302         }
303         value = value >> 1;
304         i++;
305     }
306 }
307
308 /*
309 ** Compute the nearest power of 2 number.  This algorithm is a little
310 ** strange, but it works quite well.
311 */
312 static int nearestPower(GLuint value)
313 {
314     int i;
315
316     i = 1;
317
318     /* Error! */
319     if (value == 0) return -1;
320
321     for (;;) {
322         if (value == 1) {
323             return i;
324         } else if (value == 3) {
325             return i*4;
326         }
327         value = value >> 1;
328         i *= 2;
329     }
330 }
331
332 #define __GLU_SWAP_2_BYTES(s)\
333 (GLushort)(((GLushort)((const GLubyte*)(s))[1])<<8 | ((const GLubyte*)(s))[0])
334
335 #define __GLU_SWAP_4_BYTES(s)\
336 (GLuint)(((GLuint)((const GLubyte*)(s))[3])<<24 | \
337         ((GLuint)((const GLubyte*)(s))[2])<<16 | \
338         ((GLuint)((const GLubyte*)(s))[1])<<8  | ((const GLubyte*)(s))[0])
339
340 static void halveImage(GLint components, GLuint width, GLuint height,
341                        const GLushort *datain, GLushort *dataout)
342 {
343     int i, j, k;
344     int newwidth, newheight;
345     int delta;
346     GLushort *s;
347     const GLushort *t;
348
349     newwidth = width / 2;
350     newheight = height / 2;
351     delta = width * components;
352     s = dataout;
353     t = datain;
354
355     /* Piece o' cake! */
356     for (i = 0; i < newheight; i++) {
357         for (j = 0; j < newwidth; j++) {
358             for (k = 0; k < components; k++) {
359                 s[0] = (t[0] + t[components] + t[delta] +
360                         t[delta+components] + 2) / 4;
361                 s++; t++;
362             }
363             t += components;
364         }
365         t += delta;
366     }
367 }
368
369 static void halveImage_ubyte(GLint components, GLuint width, GLuint height,
370                         const GLubyte *datain, GLubyte *dataout,
371                         GLint element_size, GLint ysize, GLint group_size)
372 {
373     int i, j, k;
374     int newwidth, newheight;
375     int padBytes;
376     GLubyte *s;
377     const char *t;
378
379     /* handle case where there is only 1 column/row */
380     if (width == 1 || height == 1) {
381        assert( !(width == 1 && height == 1) ); /* can't be 1x1 */
382        halve1Dimage_ubyte(components,width,height,datain,dataout,
383                           element_size,ysize,group_size);
384        return;
385     }
386
387     newwidth = width / 2;
388     newheight = height / 2;
389     padBytes = ysize - (width*group_size);
390     s = dataout;
391     t = (const char *)datain;
392
393     /* Piece o' cake! */
394     for (i = 0; i < newheight; i++) {
395         for (j = 0; j < newwidth; j++) {
396             for (k = 0; k < components; k++) {
397                 s[0] = (*(const GLubyte*)t +
398                         *(const GLubyte*)(t+group_size) +
399                         *(const GLubyte*)(t+ysize) +
400                         *(const GLubyte*)(t+ysize+group_size) + 2) / 4;
401                 s++; t += element_size;
402             }
403             t += group_size;
404         }
405         t += padBytes;
406         t += ysize;
407     }
408 }
409
410 /* */
411 static void halve1Dimage_ubyte(GLint components, GLuint width, GLuint height,
412                                const GLubyte *dataIn, GLubyte *dataOut,
413                                GLint element_size, GLint ysize,
414                                GLint group_size)
415 {
416    GLint halfWidth= width / 2;
417    GLint halfHeight= height / 2;
418    const char *src= (const char *) dataIn;
419    GLubyte *dest= dataOut;
420    int jj;
421
422    assert(width == 1 || height == 1); /* must be 1D */
423    assert(width != height);     /* can't be square */
424
425    if (height == 1) {           /* 1 row */
426       assert(width != 1);       /* widthxheight can't be 1x1 */
427       halfHeight= 1;
428
429       for (jj= 0; jj< halfWidth; jj++) {
430          int kk;
431          for (kk= 0; kk< components; kk++) {
432             *dest= (*(const GLubyte*)src +
433                  *(const GLubyte*)(src+group_size)) / 2;
434
435             src+= element_size;
436             dest++;
437          }
438          src+= group_size;      /* skip to next 2 */
439       }
440       {
441          int padBytes= ysize - (width*group_size);
442          src+= padBytes;        /* for assertion only */
443       }
444    }
445    else if (width == 1) {       /* 1 column */
446       int padBytes= ysize - (width * group_size);
447       assert(height != 1);      /* widthxheight can't be 1x1 */
448       halfWidth= 1;
449       /* one vertical column with possible pad bytes per row */
450       /* average two at a time */
451
452       for (jj= 0; jj< halfHeight; jj++) {
453          int kk;
454          for (kk= 0; kk< components; kk++) {
455             *dest= (*(const GLubyte*)src + *(const GLubyte*)(src+ysize)) / 2;
456
457             src+= element_size;
458             dest++;
459          }
460          src+= padBytes; /* add pad bytes, if any, to get to end to row */
461          src+= ysize;
462       }
463    }
464
465    assert(src == &((const char *)dataIn)[ysize*height]);
466    assert((char *)dest == &((char *)dataOut)
467           [components * element_size * halfWidth * halfHeight]);
468 } /* halve1Dimage_ubyte() */
469
470 static void halveImage_byte(GLint components, GLuint width, GLuint height,
471                         const GLbyte *datain, GLbyte *dataout,
472                         GLint element_size,
473                         GLint ysize, GLint group_size)
474 {
475     int i, j, k;
476     int newwidth, newheight;
477     int padBytes;
478     GLbyte *s;
479     const char *t;
480
481     /* handle case where there is only 1 column/row */
482     if (width == 1 || height == 1) {
483        assert( !(width == 1 && height == 1) ); /* can't be 1x1 */
484        halve1Dimage_byte(components,width,height,datain,dataout,
485                          element_size,ysize,group_size);
486        return;
487     }
488
489     newwidth = width / 2;
490     newheight = height / 2;
491     padBytes = ysize - (width*group_size);
492     s = dataout;
493     t = (const char *)datain;
494
495     /* Piece o' cake! */
496     for (i = 0; i < newheight; i++) {
497         for (j = 0; j < newwidth; j++) {
498             for (k = 0; k < components; k++) {
499                 s[0] = (*(const GLbyte*)t +
500                         *(const GLbyte*)(t+group_size) +
501                         *(const GLbyte*)(t+ysize) +
502                         *(const GLbyte*)(t+ysize+group_size) + 2) / 4;
503                 s++; t += element_size;
504             }
505             t += group_size;
506         }
507         t += padBytes;
508         t += ysize;
509     }
510 }
511
512 static void halve1Dimage_byte(GLint components, GLuint width, GLuint height,
513                               const GLbyte *dataIn, GLbyte *dataOut,
514                               GLint element_size,GLint ysize, GLint group_size)
515 {
516    GLint halfWidth= width / 2;
517    GLint halfHeight= height / 2;
518    const char *src= (const char *) dataIn;
519    GLbyte *dest= dataOut;
520    int jj;
521
522    assert(width == 1 || height == 1); /* must be 1D */
523    assert(width != height);     /* can't be square */
524
525    if (height == 1) {           /* 1 row */
526       assert(width != 1);       /* widthxheight can't be 1x1 */
527       halfHeight= 1;
528
529       for (jj= 0; jj< halfWidth; jj++) {
530          int kk;
531          for (kk= 0; kk< components; kk++) {
532             *dest= (*(const GLbyte*)src + *(const GLbyte*)(src+group_size)) / 2;
533
534             src+= element_size;
535             dest++;
536          }
537          src+= group_size;      /* skip to next 2 */
538       }
539       {
540          int padBytes= ysize - (width*group_size);
541          src+= padBytes;        /* for assertion only */
542       }
543    }
544    else if (width == 1) {       /* 1 column */
545       int padBytes= ysize - (width * group_size);
546       assert(height != 1);      /* widthxheight can't be 1x1 */
547       halfWidth= 1;
548       /* one vertical column with possible pad bytes per row */
549       /* average two at a time */
550
551       for (jj= 0; jj< halfHeight; jj++) {
552          int kk;
553          for (kk= 0; kk< components; kk++) {
554             *dest= (*(const GLbyte*)src + *(const GLbyte*)(src+ysize)) / 2;
555
556             src+= element_size;
557             dest++;
558          }
559          src+= padBytes; /* add pad bytes, if any, to get to end to row */
560          src+= ysize;
561       }
562
563       assert(src == &((const char *)dataIn)[ysize*height]);
564    }
565
566    assert((char *)dest == &((char *)dataOut)
567           [components * element_size * halfWidth * halfHeight]);
568 } /* halve1Dimage_byte() */
569
570 static void halveImage_ushort(GLint components, GLuint width, GLuint height,
571                         const GLushort *datain, GLushort *dataout,
572                         GLint element_size, GLint ysize, GLint group_size,
573                         GLint myswap_bytes)
574 {
575     int i, j, k;
576     int newwidth, newheight;
577     int padBytes;
578     GLushort *s;
579     const char *t;
580
581     /* handle case where there is only 1 column/row */
582     if (width == 1 || height == 1) {
583        assert( !(width == 1 && height == 1) ); /* can't be 1x1 */
584        halve1Dimage_ushort(components,width,height,datain,dataout,
585                            element_size,ysize,group_size, myswap_bytes);
586        return;
587     }
588
589     newwidth = width / 2;
590     newheight = height / 2;
591     padBytes = ysize - (width*group_size);
592     s = dataout;
593     t = (const char *)datain;
594
595     /* Piece o' cake! */
596     if (!myswap_bytes)
597     for (i = 0; i < newheight; i++) {
598         for (j = 0; j < newwidth; j++) {
599             for (k = 0; k < components; k++) {
600                 s[0] = (*(const GLushort*)t +
601                         *(const GLushort*)(t+group_size) +
602                         *(const GLushort*)(t+ysize) +
603                         *(const GLushort*)(t+ysize+group_size) + 2) / 4;
604                 s++; t += element_size;
605             }
606             t += group_size;
607         }
608         t += padBytes;
609         t += ysize;
610     }
611     else
612     for (i = 0; i < newheight; i++) {
613         for (j = 0; j < newwidth; j++) {
614             for (k = 0; k < components; k++) {
615                 s[0] = (__GLU_SWAP_2_BYTES(t) +
616                         __GLU_SWAP_2_BYTES(t+group_size) +
617                         __GLU_SWAP_2_BYTES(t+ysize) +
618                         __GLU_SWAP_2_BYTES(t+ysize+group_size)+ 2)/4;
619                 s++; t += element_size;
620             }
621             t += group_size;
622         }
623         t += padBytes;
624         t += ysize;
625     }
626 }
627
628 static void halve1Dimage_ushort(GLint components, GLuint width, GLuint height,
629                                 const GLushort *dataIn, GLushort *dataOut,
630                                 GLint element_size, GLint ysize,
631                                 GLint group_size, GLint myswap_bytes)
632 {
633    GLint halfWidth= width / 2;
634    GLint halfHeight= height / 2;
635    const char *src= (const char *) dataIn;
636    GLushort *dest= dataOut;
637    int jj;
638
639    assert(width == 1 || height == 1); /* must be 1D */
640    assert(width != height);     /* can't be square */
641
642    if (height == 1) {           /* 1 row */
643       assert(width != 1);       /* widthxheight can't be 1x1 */
644       halfHeight= 1;
645
646       for (jj= 0; jj< halfWidth; jj++) {
647          int kk;
648          for (kk= 0; kk< components; kk++) {
649 #define BOX2 2
650             GLushort ushort[BOX2];
651             if (myswap_bytes) {
652                ushort[0]= __GLU_SWAP_2_BYTES(src);
653                ushort[1]= __GLU_SWAP_2_BYTES(src+group_size);
654             }
655             else {
656                ushort[0]= *(const GLushort*)src;
657                ushort[1]= *(const GLushort*)(src+group_size);
658             }
659
660             *dest= (ushort[0] + ushort[1]) / 2;
661             src+= element_size;
662             dest++;
663          }
664          src+= group_size;      /* skip to next 2 */
665       }
666       {
667          int padBytes= ysize - (width*group_size);
668          src+= padBytes;        /* for assertion only */
669       }
670    }
671    else if (width == 1) {       /* 1 column */
672       int padBytes= ysize - (width * group_size);
673       assert(height != 1);      /* widthxheight can't be 1x1 */
674       halfWidth= 1;
675       /* one vertical column with possible pad bytes per row */
676       /* average two at a time */
677
678       for (jj= 0; jj< halfHeight; jj++) {
679          int kk;
680          for (kk= 0; kk< components; kk++) {
681 #define BOX2 2
682             GLushort ushort[BOX2];
683             if (myswap_bytes) {
684                ushort[0]= __GLU_SWAP_2_BYTES(src);
685                ushort[1]= __GLU_SWAP_2_BYTES(src+ysize);
686             }
687             else {
688                ushort[0]= *(const GLushort*)src;
689                ushort[1]= *(const GLushort*)(src+ysize);
690             }
691             *dest= (ushort[0] + ushort[1]) / 2;
692
693             src+= element_size;
694             dest++;
695          }
696          src+= padBytes; /* add pad bytes, if any, to get to end to row */
697          src+= ysize;
698       }
699
700       assert(src == &((const char *)dataIn)[ysize*height]);
701    }
702
703    assert((char *)dest == &((char *)dataOut)
704           [components * element_size * halfWidth * halfHeight]);
705
706 } /* halve1Dimage_ushort() */
707
708
709 static void halveImage_short(GLint components, GLuint width, GLuint height,
710                         const GLshort *datain, GLshort *dataout,
711                         GLint element_size, GLint ysize, GLint group_size,
712                         GLint myswap_bytes)
713 {
714     int i, j, k;
715     int newwidth, newheight;
716     int padBytes;
717     GLshort *s;
718     const char *t;
719
720     /* handle case where there is only 1 column/row */
721     if (width == 1 || height == 1) {
722        assert( !(width == 1 && height == 1) ); /* can't be 1x1 */
723        halve1Dimage_short(components,width,height,datain,dataout,
724                           element_size,ysize,group_size, myswap_bytes);
725        return;
726     }
727
728     newwidth = width / 2;
729     newheight = height / 2;
730     padBytes = ysize - (width*group_size);
731     s = dataout;
732     t = (const char *)datain;
733
734     /* Piece o' cake! */
735     if (!myswap_bytes)
736     for (i = 0; i < newheight; i++) {
737         for (j = 0; j < newwidth; j++) {
738             for (k = 0; k < components; k++) {
739                 s[0] = (*(const GLshort*)t +
740                         *(const GLshort*)(t+group_size) +
741                         *(const GLshort*)(t+ysize) +
742                         *(const GLshort*)(t+ysize+group_size) + 2) / 4;
743                 s++; t += element_size;
744             }
745             t += group_size;
746         }
747         t += padBytes;
748         t += ysize;
749     }
750     else
751     for (i = 0; i < newheight; i++) {
752         for (j = 0; j < newwidth; j++) {
753             for (k = 0; k < components; k++) {
754                 GLushort b;
755                 GLint buf;
756                 b = __GLU_SWAP_2_BYTES(t);
757                 buf = *(const GLshort*)&b;
758                 b = __GLU_SWAP_2_BYTES(t+group_size);
759                 buf += *(const GLshort*)&b;
760                 b = __GLU_SWAP_2_BYTES(t+ysize);
761                 buf += *(const GLshort*)&b;
762                 b = __GLU_SWAP_2_BYTES(t+ysize+group_size);
763                 buf += *(const GLshort*)&b;
764                 s[0] = (GLshort)((buf+2)/4);
765                 s++; t += element_size;
766             }
767             t += group_size;
768         }
769         t += padBytes;
770         t += ysize;
771     }
772 }
773
774 static void halve1Dimage_short(GLint components, GLuint width, GLuint height,
775                                 const GLshort *dataIn, GLshort *dataOut,
776                                 GLint element_size, GLint ysize,
777                                 GLint group_size, GLint myswap_bytes)
778 {
779    GLint halfWidth= width / 2;
780    GLint halfHeight= height / 2;
781    const char *src= (const char *) dataIn;
782    GLshort *dest= dataOut;
783    int jj;
784
785    assert(width == 1 || height == 1); /* must be 1D */
786    assert(width != height);     /* can't be square */
787
788    if (height == 1) {           /* 1 row */
789       assert(width != 1);       /* widthxheight can't be 1x1 */
790       halfHeight= 1;
791
792       for (jj= 0; jj< halfWidth; jj++) {
793          int kk;
794          for (kk= 0; kk< components; kk++) {
795 #define BOX2 2
796             GLshort sshort[BOX2];
797             if (myswap_bytes) {
798                sshort[0]= __GLU_SWAP_2_BYTES(src);
799                sshort[1]= __GLU_SWAP_2_BYTES(src+group_size);
800             }
801             else {
802                sshort[0]= *(const GLshort*)src;
803                sshort[1]= *(const GLshort*)(src+group_size);
804             }
805
806             *dest= (sshort[0] + sshort[1]) / 2;
807             src+= element_size;
808             dest++;
809          }
810          src+= group_size;      /* skip to next 2 */
811       }
812       {
813          int padBytes= ysize - (width*group_size);
814          src+= padBytes;        /* for assertion only */
815       }
816    }
817    else if (width == 1) {       /* 1 column */
818       int padBytes= ysize - (width * group_size);
819       assert(height != 1);      /* widthxheight can't be 1x1 */
820       halfWidth= 1;
821       /* one vertical column with possible pad bytes per row */
822       /* average two at a time */
823
824       for (jj= 0; jj< halfHeight; jj++) {
825          int kk;
826          for (kk= 0; kk< components; kk++) {
827 #define BOX2 2
828             GLshort sshort[BOX2];
829             if (myswap_bytes) {
830                sshort[0]= __GLU_SWAP_2_BYTES(src);
831                sshort[1]= __GLU_SWAP_2_BYTES(src+ysize);
832             }
833             else {
834                sshort[0]= *(const GLshort*)src;
835                sshort[1]= *(const GLshort*)(src+ysize);
836             }
837             *dest= (sshort[0] + sshort[1]) / 2;
838
839             src+= element_size;
840             dest++;
841          }
842          src+= padBytes; /* add pad bytes, if any, to get to end to row */
843          src+= ysize;
844       }
845
846       assert(src == &((const char *)dataIn)[ysize*height]);
847    }
848
849    assert((char *)dest == &((char *)dataOut)
850           [components * element_size * halfWidth * halfHeight]);
851
852 } /* halve1Dimage_short() */
853
854
855 static void halveImage_uint(GLint components, GLuint width, GLuint height,
856                         const GLuint *datain, GLuint *dataout,
857                         GLint element_size, GLint ysize, GLint group_size,
858                         GLint myswap_bytes)
859 {
860     int i, j, k;
861     int newwidth, newheight;
862     int padBytes;
863     GLuint *s;
864     const char *t;
865
866     /* handle case where there is only 1 column/row */
867     if (width == 1 || height == 1) {
868        assert( !(width == 1 && height == 1) ); /* can't be 1x1 */
869        halve1Dimage_uint(components,width,height,datain,dataout,
870                          element_size,ysize,group_size, myswap_bytes);
871        return;
872     }
873
874     newwidth = width / 2;
875     newheight = height / 2;
876     padBytes = ysize - (width*group_size);
877     s = dataout;
878     t = (const char *)datain;
879
880     /* Piece o' cake! */
881     if (!myswap_bytes)
882     for (i = 0; i < newheight; i++) {
883         for (j = 0; j < newwidth; j++) {
884             for (k = 0; k < components; k++) {
885                 /* need to cast to double to hold large unsigned ints */
886                 s[0] = ((double)*(const GLuint*)t +
887                         (double)*(const GLuint*)(t+group_size) +
888                         (double)*(const GLuint*)(t+ysize) +
889                         (double)*(const GLuint*)(t+ysize+group_size))/4 + 0.5;
890                 s++; t += element_size;
891
892             }
893             t += group_size;
894         }
895         t += padBytes;
896         t += ysize;
897     }
898     else
899     for (i = 0; i < newheight; i++) {
900         for (j = 0; j < newwidth; j++) {
901             for (k = 0; k < components; k++) {
902                 /* need to cast to double to hold large unsigned ints */
903                 GLdouble buf;
904                 buf = (GLdouble)__GLU_SWAP_4_BYTES(t) +
905                       (GLdouble)__GLU_SWAP_4_BYTES(t+group_size) +
906                       (GLdouble)__GLU_SWAP_4_BYTES(t+ysize) +
907                       (GLdouble)__GLU_SWAP_4_BYTES(t+ysize+group_size);
908                 s[0] = (GLuint)(buf/4 + 0.5);
909
910                 s++; t += element_size;
911             }
912             t += group_size;
913         }
914         t += padBytes;
915         t += ysize;
916     }
917 }
918
919 /* */
920 static void halve1Dimage_uint(GLint components, GLuint width, GLuint height,
921                               const GLuint *dataIn, GLuint *dataOut,
922                               GLint element_size, GLint ysize,
923                               GLint group_size, GLint myswap_bytes)
924 {
925    GLint halfWidth= width / 2;
926    GLint halfHeight= height / 2;
927    const char *src= (const char *) dataIn;
928    GLuint *dest= dataOut;
929    int jj;
930
931    assert(width == 1 || height == 1); /* must be 1D */
932    assert(width != height);     /* can't be square */
933
934    if (height == 1) {           /* 1 row */
935       assert(width != 1);       /* widthxheight can't be 1x1 */
936       halfHeight= 1;
937
938       for (jj= 0; jj< halfWidth; jj++) {
939          int kk;
940          for (kk= 0; kk< components; kk++) {
941 #define BOX2 2
942             GLuint uint[BOX2];
943             if (myswap_bytes) {
944                uint[0]= __GLU_SWAP_4_BYTES(src);
945                uint[1]= __GLU_SWAP_4_BYTES(src+group_size);
946             }
947             else {
948                uint[0]= *(const GLuint*)src;
949                uint[1]= *(const GLuint*)(src+group_size);
950             }
951             *dest= ((double)uint[0]+(double)uint[1])/2.0;
952
953             src+= element_size;
954             dest++;
955          }
956          src+= group_size;      /* skip to next 2 */
957       }
958       {
959          int padBytes= ysize - (width*group_size);
960          src+= padBytes;        /* for assertion only */
961       }
962    }
963    else if (width == 1) {       /* 1 column */
964       int padBytes= ysize - (width * group_size);
965       assert(height != 1);      /* widthxheight can't be 1x1 */
966       halfWidth= 1;
967       /* one vertical column with possible pad bytes per row */
968       /* average two at a time */
969
970       for (jj= 0; jj< halfHeight; jj++) {
971          int kk;
972          for (kk= 0; kk< components; kk++) {
973 #define BOX2 2
974             GLuint uint[BOX2];
975             if (myswap_bytes) {
976                uint[0]= __GLU_SWAP_4_BYTES(src);
977                uint[1]= __GLU_SWAP_4_BYTES(src+ysize);
978             }
979             else {
980                uint[0]= *(const GLuint*)src;
981                uint[1]= *(const GLuint*)(src+ysize);
982             }
983             *dest= ((double)uint[0]+(double)uint[1])/2.0;
984
985             src+= element_size;
986             dest++;
987          }
988          src+= padBytes; /* add pad bytes, if any, to get to end to row */
989          src+= ysize;
990       }
991
992       assert(src == &((const char *)dataIn)[ysize*height]);
993    }
994
995    assert((char *)dest == &((char *)dataOut)
996           [components * element_size * halfWidth * halfHeight]);
997
998 } /* halve1Dimage_uint() */
999
1000 static void halveImage_int(GLint components, GLuint width, GLuint height,
1001                         const GLint *datain, GLint *dataout, GLint element_size,
1002                         GLint ysize, GLint group_size, GLint myswap_bytes)
1003 {
1004     int i, j, k;
1005     int newwidth, newheight;
1006     int padBytes;
1007     GLint *s;
1008     const char *t;
1009
1010     /* handle case where there is only 1 column/row */
1011     if (width == 1 || height == 1) {
1012        assert( !(width == 1 && height == 1) ); /* can't be 1x1 */
1013        halve1Dimage_int(components,width,height,datain,dataout,
1014                         element_size,ysize,group_size, myswap_bytes);
1015        return;
1016     }
1017
1018     newwidth = width / 2;
1019     newheight = height / 2;
1020     padBytes = ysize - (width*group_size);
1021     s = dataout;
1022     t = (const char *)datain;
1023
1024     /* Piece o' cake! */
1025     if (!myswap_bytes)
1026     for (i = 0; i < newheight; i++) {
1027         for (j = 0; j < newwidth; j++) {
1028             for (k = 0; k < components; k++) {
1029                 s[0] = ((float)*(const GLint*)t +
1030                         (float)*(const GLint*)(t+group_size) +
1031                         (float)*(const GLint*)(t+ysize) +
1032                         (float)*(const GLint*)(t+ysize+group_size))/4 + 0.5;
1033                 s++; t += element_size;
1034             }
1035             t += group_size;
1036         }
1037         t += padBytes;
1038         t += ysize;
1039     }
1040     else
1041     for (i = 0; i < newheight; i++) {
1042         for (j = 0; j < newwidth; j++) {
1043             for (k = 0; k < components; k++) {
1044                 GLuint b;
1045                 GLfloat buf;
1046                 b = __GLU_SWAP_4_BYTES(t);
1047                 buf = *(GLint*)&b;
1048                 b = __GLU_SWAP_4_BYTES(t+group_size);
1049                 buf += *(GLint*)&b;
1050                 b = __GLU_SWAP_4_BYTES(t+ysize);
1051                 buf += *(GLint*)&b;
1052                 b = __GLU_SWAP_4_BYTES(t+ysize+group_size);
1053                 buf += *(GLint*)&b;
1054                 s[0] = (GLint)(buf/4 + 0.5);
1055
1056                 s++; t += element_size;
1057             }
1058             t += group_size;
1059         }
1060         t += padBytes;
1061         t += ysize;
1062     }
1063 }
1064
1065 /* */
1066 static void halve1Dimage_int(GLint components, GLuint width, GLuint height,
1067                              const GLint *dataIn, GLint *dataOut,
1068                              GLint element_size, GLint ysize,
1069                              GLint group_size, GLint myswap_bytes)
1070 {
1071    GLint halfWidth= width / 2;
1072    GLint halfHeight= height / 2;
1073    const char *src= (const char *) dataIn;
1074    GLint *dest= dataOut;
1075    int jj;
1076
1077    assert(width == 1 || height == 1); /* must be 1D */
1078    assert(width != height);     /* can't be square */
1079
1080    if (height == 1) {           /* 1 row */
1081       assert(width != 1);       /* widthxheight can't be 1x1 */
1082       halfHeight= 1;
1083
1084       for (jj= 0; jj< halfWidth; jj++) {
1085          int kk;
1086          for (kk= 0; kk< components; kk++) {
1087 #define BOX2 2
1088             GLuint uint[BOX2];
1089             if (myswap_bytes) {
1090                uint[0]= __GLU_SWAP_4_BYTES(src);
1091                uint[1]= __GLU_SWAP_4_BYTES(src+group_size);
1092             }
1093             else {
1094                uint[0]= *(const GLuint*)src;
1095                uint[1]= *(const GLuint*)(src+group_size);
1096             }
1097             *dest= ((float)uint[0]+(float)uint[1])/2.0;
1098
1099             src+= element_size;
1100             dest++;
1101          }
1102          src+= group_size;      /* skip to next 2 */
1103       }
1104       {
1105          int padBytes= ysize - (width*group_size);
1106          src+= padBytes;        /* for assertion only */
1107       }
1108    }
1109    else if (width == 1) {       /* 1 column */
1110       int padBytes= ysize - (width * group_size);
1111       assert(height != 1);      /* widthxheight can't be 1x1 */
1112       halfWidth= 1;
1113       /* one vertical column with possible pad bytes per row */
1114       /* average two at a time */
1115
1116       for (jj= 0; jj< halfHeight; jj++) {
1117          int kk;
1118          for (kk= 0; kk< components; kk++) {
1119 #define BOX2 2
1120             GLuint uint[BOX2];
1121             if (myswap_bytes) {
1122                uint[0]= __GLU_SWAP_4_BYTES(src);
1123                uint[1]= __GLU_SWAP_4_BYTES(src+ysize);
1124             }
1125             else {
1126                uint[0]= *(const GLuint*)src;
1127                uint[1]= *(const GLuint*)(src+ysize);
1128             }
1129             *dest= ((float)uint[0]+(float)uint[1])/2.0;
1130
1131             src+= element_size;
1132             dest++;
1133          }
1134          src+= padBytes; /* add pad bytes, if any, to get to end to row */
1135          src+= ysize;
1136       }
1137
1138       assert(src == &((const char *)dataIn)[ysize*height]);
1139    }
1140
1141    assert((char *)dest == &((char *)dataOut)
1142           [components * element_size * halfWidth * halfHeight]);
1143
1144 } /* halve1Dimage_int() */
1145
1146
1147 static void halveImage_float(GLint components, GLuint width, GLuint height,
1148                         const GLfloat *datain, GLfloat *dataout,
1149                         GLint element_size, GLint ysize, GLint group_size,
1150                         GLint myswap_bytes)
1151 {
1152     int i, j, k;
1153     int newwidth, newheight;
1154     int padBytes;
1155     GLfloat *s;
1156     const char *t;
1157
1158     /* handle case where there is only 1 column/row */
1159     if (width == 1 || height == 1) {
1160        assert( !(width == 1 && height == 1) ); /* can't be 1x1 */
1161        halve1Dimage_float(components,width,height,datain,dataout,
1162                           element_size,ysize,group_size, myswap_bytes);
1163        return;
1164     }
1165
1166     newwidth = width / 2;
1167     newheight = height / 2;
1168     padBytes = ysize - (width*group_size);
1169     s = dataout;
1170     t = (const char *)datain;
1171
1172     /* Piece o' cake! */
1173     if (!myswap_bytes)
1174     for (i = 0; i < newheight; i++) {
1175         for (j = 0; j < newwidth; j++) {
1176             for (k = 0; k < components; k++) {
1177                 s[0] = (*(const GLfloat*)t +
1178                         *(const GLfloat*)(t+group_size) +
1179                         *(const GLfloat*)(t+ysize) +
1180                         *(const GLfloat*)(t+ysize+group_size)) / 4;
1181                 s++; t += element_size;
1182             }
1183             t += group_size;
1184         }
1185         t += padBytes;
1186         t += ysize;
1187     }
1188     else
1189     for (i = 0; i < newheight; i++) {
1190         for (j = 0; j < newwidth; j++) {
1191             for (k = 0; k < components; k++) {
1192                 union { GLuint b; GLfloat f; } swapbuf;
1193                 swapbuf.b = __GLU_SWAP_4_BYTES(t);
1194                 s[0] = swapbuf.f;
1195                 swapbuf.b = __GLU_SWAP_4_BYTES(t+group_size);
1196                 s[0] += swapbuf.f;
1197                 swapbuf.b = __GLU_SWAP_4_BYTES(t+ysize);
1198                 s[0] += swapbuf.f;
1199                 swapbuf.b = __GLU_SWAP_4_BYTES(t+ysize+group_size);
1200                 s[0] += swapbuf.f;
1201                 s[0] /= 4;
1202                 s++; t += element_size;
1203             }
1204             t += group_size;
1205         }
1206         t += padBytes;
1207         t += ysize;
1208     }
1209 }
1210
1211 /* */
1212 static void halve1Dimage_float(GLint components, GLuint width, GLuint height,
1213                                const GLfloat *dataIn, GLfloat *dataOut,
1214                                GLint element_size, GLint ysize,
1215                                GLint group_size, GLint myswap_bytes)
1216 {
1217    GLint halfWidth= width / 2;
1218    GLint halfHeight= height / 2;
1219    const char *src= (const char *) dataIn;
1220    GLfloat *dest= dataOut;
1221    int jj;
1222
1223    assert(width == 1 || height == 1); /* must be 1D */
1224    assert(width != height);     /* can't be square */
1225
1226    if (height == 1) {           /* 1 row */
1227       assert(width != 1);       /* widthxheight can't be 1x1 */
1228       halfHeight= 1;
1229
1230       for (jj= 0; jj< halfWidth; jj++) {
1231          int kk;
1232          for (kk= 0; kk< components; kk++) {
1233 #define BOX2 2
1234             GLfloat sfloat[BOX2];
1235             if (myswap_bytes) {
1236                sfloat[0]= __GLU_SWAP_4_BYTES(src);
1237                sfloat[1]= __GLU_SWAP_4_BYTES(src+group_size);
1238             }
1239             else {
1240                sfloat[0]= *(const GLfloat*)src;
1241                sfloat[1]= *(const GLfloat*)(src+group_size);
1242             }
1243
1244             *dest= (sfloat[0] + sfloat[1]) / 2.0;
1245             src+= element_size;
1246             dest++;
1247          }
1248          src+= group_size;      /* skip to next 2 */
1249       }
1250       {
1251          int padBytes= ysize - (width*group_size);
1252          src+= padBytes;        /* for assertion only */
1253       }
1254    }
1255    else if (width == 1) {       /* 1 column */
1256       int padBytes= ysize - (width * group_size);
1257       assert(height != 1);      /* widthxheight can't be 1x1 */
1258       halfWidth= 1;
1259       /* one vertical column with possible pad bytes per row */
1260       /* average two at a time */
1261
1262       for (jj= 0; jj< halfHeight; jj++) {
1263          int kk;
1264          for (kk= 0; kk< components; kk++) {
1265 #define BOX2 2
1266             GLfloat sfloat[BOX2];
1267             if (myswap_bytes) {
1268                sfloat[0]= __GLU_SWAP_4_BYTES(src);
1269                sfloat[1]= __GLU_SWAP_4_BYTES(src+ysize);
1270             }
1271             else {
1272                sfloat[0]= *(const GLfloat*)src;
1273                sfloat[1]= *(const GLfloat*)(src+ysize);
1274             }
1275             *dest= (sfloat[0] + sfloat[1]) / 2.0;
1276
1277             src+= element_size;
1278             dest++;
1279          }
1280          src+= padBytes; /* add pad bytes, if any, to get to end to row */
1281          src+= ysize;           /* skip to odd row */
1282       }
1283    }
1284
1285    assert(src == &((const char *)dataIn)[ysize*height]);
1286    assert((char *)dest == &((char *)dataOut)
1287           [components * element_size * halfWidth * halfHeight]);
1288 } /* halve1Dimage_float() */
1289
1290 static void scale_internal(GLint components, GLint widthin, GLint heightin,
1291                            const GLushort *datain,
1292                            GLint widthout, GLint heightout,
1293                            GLushort *dataout)
1294 {
1295     float x, lowx, highx, convx, halfconvx;
1296     float y, lowy, highy, convy, halfconvy;
1297     float xpercent,ypercent;
1298     float percent;
1299     /* Max components in a format is 4, so... */
1300     float totals[4];
1301     float area;
1302     int i,j,k,yint,xint,xindex,yindex;
1303     int temp;
1304
1305     if (widthin == widthout*2 && heightin == heightout*2) {
1306         halveImage(components, widthin, heightin, datain, dataout);
1307         return;
1308     }
1309     convy = (float) heightin/heightout;
1310     convx = (float) widthin/widthout;
1311     halfconvx = convx/2;
1312     halfconvy = convy/2;
1313     for (i = 0; i < heightout; i++) {
1314         y = convy * (i+0.5);
1315         if (heightin > heightout) {
1316             highy = y + halfconvy;
1317             lowy = y - halfconvy;
1318         } else {
1319             highy = y + 0.5;
1320             lowy = y - 0.5;
1321         }
1322         for (j = 0; j < widthout; j++) {
1323             x = convx * (j+0.5);
1324             if (widthin > widthout) {
1325                 highx = x + halfconvx;
1326                 lowx = x - halfconvx;
1327             } else {
1328                 highx = x + 0.5;
1329                 lowx = x - 0.5;
1330             }
1331
1332             /*
1333             ** Ok, now apply box filter to box that goes from (lowx, lowy)
1334             ** to (highx, highy) on input data into this pixel on output
1335             ** data.
1336             */
1337             totals[0] = totals[1] = totals[2] = totals[3] = 0.0;
1338             area = 0.0;
1339
1340             y = lowy;
1341             yint = floor(y);
1342             while (y < highy) {
1343                 yindex = (yint + heightin) % heightin;
1344                 if (highy < yint+1) {
1345                     ypercent = highy - y;
1346                 } else {
1347                     ypercent = yint+1 - y;
1348                 }
1349
1350                 x = lowx;
1351                 xint = floor(x);
1352
1353                 while (x < highx) {
1354                     xindex = (xint + widthin) % widthin;
1355                     if (highx < xint+1) {
1356                         xpercent = highx - x;
1357                     } else {
1358                         xpercent = xint+1 - x;
1359                     }
1360
1361                     percent = xpercent * ypercent;
1362                     area += percent;
1363                     temp = (xindex + (yindex * widthin)) * components;
1364                     for (k = 0; k < components; k++) {
1365                         totals[k] += datain[temp + k] * percent;
1366                     }
1367
1368                     xint++;
1369                     x = xint;
1370                 }
1371                 yint++;
1372                 y = yint;
1373             }
1374
1375             temp = (j + (i * widthout)) * components;
1376             for (k = 0; k < components; k++) {
1377                 /* totals[] should be rounded in the case of enlarging an RGB
1378                  * ramp when the type is 332 or 4444
1379                  */
1380                 dataout[temp + k] = (totals[k]+0.5)/area;
1381             }
1382         }
1383     }
1384 }
1385
1386 static void scale_internal_ubyte(GLint components, GLint widthin,
1387                            GLint heightin, const GLubyte *datain,
1388                            GLint widthout, GLint heightout,
1389                            GLubyte *dataout, GLint element_size,
1390                            GLint ysize, GLint group_size)
1391 {
1392     float convx;
1393     float convy;
1394     float percent;
1395     /* Max components in a format is 4, so... */
1396     float totals[4];
1397     float area;
1398     int i,j,k,xindex;
1399
1400     const char *temp, *temp0;
1401     const char *temp_index;
1402     int outindex;
1403
1404     int lowx_int, highx_int, lowy_int, highy_int;
1405     float x_percent, y_percent;
1406     float lowx_float, highx_float, lowy_float, highy_float;
1407     float convy_float, convx_float;
1408     int convy_int, convx_int;
1409     int l, m;
1410     const char *left, *right;
1411
1412     if (widthin == widthout*2 && heightin == heightout*2) {
1413         halveImage_ubyte(components, widthin, heightin,
1414         (const GLubyte *)datain, (GLubyte *)dataout,
1415         element_size, ysize, group_size);
1416         return;
1417     }
1418     convy = (float) heightin/heightout;
1419     convx = (float) widthin/widthout;
1420     convy_int = floor(convy);
1421     convy_float = convy - convy_int;
1422     convx_int = floor(convx);
1423     convx_float = convx - convx_int;
1424
1425     area = convx * convy;
1426
1427     lowy_int = 0;
1428     lowy_float = 0;
1429     highy_int = convy_int;
1430     highy_float = convy_float;
1431
1432     for (i = 0; i < heightout; i++) {
1433         /* Clamp here to be sure we don't read beyond input buffer. */
1434         if (highy_int >= heightin)
1435             highy_int = heightin - 1;
1436         lowx_int = 0;
1437         lowx_float = 0;
1438         highx_int = convx_int;
1439         highx_float = convx_float;
1440
1441         for (j = 0; j < widthout; j++) {
1442
1443             /*
1444             ** Ok, now apply box filter to box that goes from (lowx, lowy)
1445             ** to (highx, highy) on input data into this pixel on output
1446             ** data.
1447             */
1448             totals[0] = totals[1] = totals[2] = totals[3] = 0.0;
1449
1450             /* calculate the value for pixels in the 1st row */
1451             xindex = lowx_int*group_size;
1452             if((highy_int>lowy_int) && (highx_int>lowx_int)) {
1453
1454                 y_percent = 1-lowy_float;
1455                 temp = (const char *)datain + xindex + lowy_int * ysize;
1456                 percent = y_percent * (1-lowx_float);
1457                 for (k = 0, temp_index = temp; k < components;
1458                      k++, temp_index += element_size) {
1459                         totals[k] += (GLubyte)(*(temp_index)) * percent;
1460                 }
1461                 left = temp;
1462                 for(l = lowx_int+1; l < highx_int; l++) {
1463                     temp += group_size;
1464                     for (k = 0, temp_index = temp; k < components;
1465                          k++, temp_index += element_size) {
1466                         totals[k] += (GLubyte)(*(temp_index)) * y_percent;
1467                     }
1468                 }
1469                 temp += group_size;
1470                 right = temp;
1471                 percent = y_percent * highx_float;
1472                 for (k = 0, temp_index = temp; k < components;
1473                      k++, temp_index += element_size) {
1474                         totals[k] += (GLubyte)(*(temp_index)) * percent;
1475                 }
1476
1477                 /* calculate the value for pixels in the last row */
1478                 y_percent = highy_float;
1479                 percent = y_percent * (1-lowx_float);
1480                 temp = (const char *)datain + xindex + highy_int * ysize;
1481                 for (k = 0, temp_index = temp; k < components;
1482                      k++, temp_index += element_size) {
1483                         totals[k] += (GLubyte)(*(temp_index)) * percent;
1484                 }
1485                 for(l = lowx_int+1; l < highx_int; l++) {
1486                     temp += group_size;
1487                     for (k = 0, temp_index = temp; k < components;
1488                          k++, temp_index += element_size) {
1489                         totals[k] += (GLubyte)(*(temp_index)) * y_percent;
1490                     }
1491                 }
1492                 temp += group_size;
1493                 percent = y_percent * highx_float;
1494                 for (k = 0, temp_index = temp; k < components;
1495                      k++, temp_index += element_size) {
1496                         totals[k] += (GLubyte)(*(temp_index)) * percent;
1497                 }
1498
1499
1500                 /* calculate the value for pixels in the 1st and last column */
1501                 for(m = lowy_int+1; m < highy_int; m++) {
1502                     left += ysize;
1503                     right += ysize;
1504                     for (k = 0; k < components;
1505                          k++, left += element_size, right += element_size) {
1506                         totals[k] += (GLubyte)(*(left))*(1-lowx_float)
1507                                 +(GLubyte)(*(right))*highx_float;
1508                     }
1509                 }
1510             } else if (highy_int > lowy_int) {
1511                 x_percent = highx_float - lowx_float;
1512                 percent = (1-lowy_float)*x_percent;
1513                 temp = (const char *)datain + xindex + lowy_int*ysize;
1514                 for (k = 0, temp_index = temp; k < components;
1515                      k++, temp_index += element_size) {
1516                         totals[k] += (GLubyte)(*(temp_index)) * percent;
1517                 }
1518                 for(m = lowy_int+1; m < highy_int; m++) {
1519                     temp += ysize;
1520                     for (k = 0, temp_index = temp; k < components;
1521                          k++, temp_index += element_size) {
1522                         totals[k] += (GLubyte)(*(temp_index)) * x_percent;
1523                     }
1524                 }
1525                 percent = x_percent * highy_float;
1526                 temp += ysize;
1527                 for (k = 0, temp_index = temp; k < components;
1528                      k++, temp_index += element_size) {
1529                         totals[k] += (GLubyte)(*(temp_index)) * percent;
1530                 }
1531             } else if (highx_int > lowx_int) {
1532                 y_percent = highy_float - lowy_float;
1533                 percent = (1-lowx_float)*y_percent;
1534                 temp = (const char *)datain + xindex + lowy_int*ysize;
1535                 for (k = 0, temp_index = temp; k < components;
1536                      k++, temp_index += element_size) {
1537                         totals[k] += (GLubyte)(*(temp_index)) * percent;
1538                 }
1539                 for (l = lowx_int+1; l < highx_int; l++) {
1540                     temp += group_size;
1541                     for (k = 0, temp_index = temp; k < components;
1542                          k++, temp_index += element_size) {
1543                         totals[k] += (GLubyte)(*(temp_index)) * y_percent;
1544                     }
1545                 }
1546                 temp += group_size;
1547                 percent = y_percent * highx_float;
1548                 for (k = 0, temp_index = temp; k < components;
1549                      k++, temp_index += element_size) {
1550                         totals[k] += (GLubyte)(*(temp_index)) * percent;
1551                 }
1552             } else {
1553                 percent = (highy_float-lowy_float)*(highx_float-lowx_float);
1554                 temp = (const char *)datain + xindex + lowy_int * ysize;
1555                 for (k = 0, temp_index = temp; k < components;
1556                      k++, temp_index += element_size) {
1557                         totals[k] += (GLubyte)(*(temp_index)) * percent;
1558                 }
1559             }
1560
1561
1562
1563             /* this is for the pixels in the body */
1564             temp0 = (const char *)datain + xindex + group_size +
1565                  (lowy_int+1)*ysize;
1566             for (m = lowy_int+1; m < highy_int; m++) {
1567                 temp = temp0;
1568                 for(l = lowx_int+1; l < highx_int; l++) {
1569                     for (k = 0, temp_index = temp; k < components;
1570                          k++, temp_index += element_size) {
1571                         totals[k] += (GLubyte)(*(temp_index));
1572                     }
1573                     temp += group_size;
1574                 }
1575                 temp0 += ysize;
1576             }
1577
1578             outindex = (j + (i * widthout)) * components;
1579             for (k = 0; k < components; k++) {
1580                 dataout[outindex + k] = totals[k]/area;
1581                 /*printf("totals[%d] = %f\n", k, totals[k]);*/
1582             }
1583             lowx_int = highx_int;
1584             lowx_float = highx_float;
1585             highx_int += convx_int;
1586             highx_float += convx_float;
1587             if(highx_float > 1) {
1588                 highx_float -= 1.0;
1589                 highx_int++;
1590             }
1591         }
1592         lowy_int = highy_int;
1593         lowy_float = highy_float;
1594         highy_int += convy_int;
1595         highy_float += convy_float;
1596         if(highy_float > 1) {
1597             highy_float -= 1.0;
1598             highy_int++;
1599         }
1600     }
1601 }
1602
1603 static void scale_internal_byte(GLint components, GLint widthin,
1604                            GLint heightin, const GLbyte *datain,
1605                            GLint widthout, GLint heightout,
1606                            GLbyte *dataout, GLint element_size,
1607                            GLint ysize, GLint group_size)
1608 {
1609     float convx;
1610     float convy;
1611     float percent;
1612     /* Max components in a format is 4, so... */
1613     float totals[4];
1614     float area;
1615     int i,j,k,xindex;
1616
1617     const char *temp, *temp0;
1618     const char *temp_index;
1619     int outindex;
1620
1621     int lowx_int, highx_int, lowy_int, highy_int;
1622     float x_percent, y_percent;
1623     float lowx_float, highx_float, lowy_float, highy_float;
1624     float convy_float, convx_float;
1625     int convy_int, convx_int;
1626     int l, m;
1627     const char *left, *right;
1628
1629     if (widthin == widthout*2 && heightin == heightout*2) {
1630         halveImage_byte(components, widthin, heightin,
1631         (const GLbyte *)datain, (GLbyte *)dataout,
1632         element_size, ysize, group_size);
1633         return;
1634     }
1635     convy = (float) heightin/heightout;
1636     convx = (float) widthin/widthout;
1637     convy_int = floor(convy);
1638     convy_float = convy - convy_int;
1639     convx_int = floor(convx);
1640     convx_float = convx - convx_int;
1641
1642     area = convx * convy;
1643
1644     lowy_int = 0;
1645     lowy_float = 0;
1646     highy_int = convy_int;
1647     highy_float = convy_float;
1648
1649     for (i = 0; i < heightout; i++) {
1650         /* Clamp here to be sure we don't read beyond input buffer. */
1651         if (highy_int >= heightin)
1652             highy_int = heightin - 1;
1653         lowx_int = 0;
1654         lowx_float = 0;
1655         highx_int = convx_int;
1656         highx_float = convx_float;
1657
1658         for (j = 0; j < widthout; j++) {
1659
1660             /*
1661             ** Ok, now apply box filter to box that goes from (lowx, lowy)
1662             ** to (highx, highy) on input data into this pixel on output
1663             ** data.
1664             */
1665             totals[0] = totals[1] = totals[2] = totals[3] = 0.0;
1666
1667             /* calculate the value for pixels in the 1st row */
1668             xindex = lowx_int*group_size;
1669             if((highy_int>lowy_int) && (highx_int>lowx_int)) {
1670
1671                 y_percent = 1-lowy_float;
1672                 temp = (const char *)datain + xindex + lowy_int * ysize;
1673                 percent = y_percent * (1-lowx_float);
1674                 for (k = 0, temp_index = temp; k < components;
1675                      k++, temp_index += element_size) {
1676                         totals[k] += (GLbyte)(*(temp_index)) * percent;
1677                 }
1678                 left = temp;
1679                 for(l = lowx_int+1; l < highx_int; l++) {
1680                     temp += group_size;
1681                     for (k = 0, temp_index = temp; k < components;
1682                      k++, temp_index += element_size) {
1683                         totals[k] += (GLbyte)(*(temp_index)) * y_percent;
1684                     }
1685                 }
1686                 temp += group_size;
1687                 right = temp;
1688                 percent = y_percent * highx_float;
1689                 for (k = 0, temp_index = temp; k < components;
1690                      k++, temp_index += element_size) {
1691                         totals[k] += (GLbyte)(*(temp_index)) * percent;
1692                 }
1693
1694                 /* calculate the value for pixels in the last row */            
1695                 y_percent = highy_float;
1696                 percent = y_percent * (1-lowx_float);
1697                 temp = (const char *)datain + xindex + highy_int * ysize;
1698                 for (k = 0, temp_index = temp; k < components;
1699                      k++, temp_index += element_size) {
1700                         totals[k] += (GLbyte)(*(temp_index)) * percent;
1701                 }
1702                 for(l = lowx_int+1; l < highx_int; l++) {
1703                     temp += group_size;
1704                     for (k = 0, temp_index = temp; k < components;
1705                          k++, temp_index += element_size) {
1706                         totals[k] += (GLbyte)(*(temp_index)) * y_percent;
1707                     }
1708                 }
1709                 temp += group_size;
1710                 percent = y_percent * highx_float;
1711                 for (k = 0, temp_index = temp; k < components;
1712                      k++, temp_index += element_size) {
1713                         totals[k] += (GLbyte)(*(temp_index)) * percent;
1714                 }
1715
1716
1717                 /* calculate the value for pixels in the 1st and last column */
1718                 for(m = lowy_int+1; m < highy_int; m++) {
1719                     left += ysize;
1720                     right += ysize;
1721                     for (k = 0; k < components;
1722                          k++, left += element_size, right += element_size) {
1723                         totals[k] += (GLbyte)(*(left))*(1-lowx_float)
1724                                 +(GLbyte)(*(right))*highx_float;
1725                     }
1726                 }
1727             } else if (highy_int > lowy_int) {
1728                 x_percent = highx_float - lowx_float;
1729                 percent = (1-lowy_float)*x_percent;
1730                 temp = (const char *)datain + xindex + lowy_int*ysize;
1731                 for (k = 0, temp_index = temp; k < components;
1732                      k++, temp_index += element_size) {
1733                         totals[k] += (GLbyte)(*(temp_index)) * percent;
1734                 }
1735                 for(m = lowy_int+1; m < highy_int; m++) {
1736                     temp += ysize;
1737                     for (k = 0, temp_index = temp; k < components;
1738                          k++, temp_index += element_size) {
1739                         totals[k] += (GLbyte)(*(temp_index)) * x_percent;
1740                     }
1741                 }
1742                 percent = x_percent * highy_float;
1743                 temp += ysize;
1744                 for (k = 0, temp_index = temp; k < components;
1745                      k++, temp_index += element_size) {
1746                         totals[k] += (GLbyte)(*(temp_index)) * percent;
1747                 }
1748             } else if (highx_int > lowx_int) {
1749                 y_percent = highy_float - lowy_float;
1750                 percent = (1-lowx_float)*y_percent;
1751                 temp = (const char *)datain + xindex + lowy_int*ysize;
1752                 for (k = 0, temp_index = temp; k < components;
1753                      k++, temp_index += element_size) {
1754                         totals[k] += (GLbyte)(*(temp_index)) * percent;
1755                 }
1756                 for (l = lowx_int+1; l < highx_int; l++) {
1757                     temp += group_size;
1758                     for (k = 0, temp_index = temp; k < components;
1759                          k++, temp_index += element_size) {
1760                         totals[k] += (GLbyte)(*(temp_index)) * y_percent;
1761                     }
1762                 }
1763                 temp += group_size;
1764                 percent = y_percent * highx_float;
1765                 for (k = 0, temp_index = temp; k < components;
1766                      k++, temp_index += element_size) {
1767                         totals[k] += (GLbyte)(*(temp_index)) * percent;
1768                 }
1769             } else {
1770                 percent = (highy_float-lowy_float)*(highx_float-lowx_float);
1771                 temp = (const char *)datain + xindex + lowy_int * ysize;
1772                 for (k = 0, temp_index = temp; k < components;
1773                      k++, temp_index += element_size) {
1774                         totals[k] += (GLbyte)(*(temp_index)) * percent;
1775                 }
1776             }
1777
1778
1779
1780             /* this is for the pixels in the body */
1781             temp0 = (const char *)datain + xindex + group_size +
1782                 (lowy_int+1)*ysize;
1783             for (m = lowy_int+1; m < highy_int; m++) {
1784                 temp = temp0;
1785                 for(l = lowx_int+1; l < highx_int; l++) {
1786                     for (k = 0, temp_index = temp; k < components;
1787                      k++, temp_index += element_size) {
1788                         totals[k] += (GLbyte)(*(temp_index));
1789                     }
1790                     temp += group_size;
1791                 }
1792                 temp0 += ysize;
1793             }
1794
1795             outindex = (j + (i * widthout)) * components;
1796             for (k = 0; k < components; k++) {
1797                 dataout[outindex + k] = totals[k]/area;
1798                 /*printf("totals[%d] = %f\n", k, totals[k]);*/
1799             }
1800             lowx_int = highx_int;
1801             lowx_float = highx_float;
1802             highx_int += convx_int;
1803             highx_float += convx_float;
1804             if(highx_float > 1) {
1805                 highx_float -= 1.0;
1806                 highx_int++;
1807             }
1808         }
1809         lowy_int = highy_int;
1810         lowy_float = highy_float;
1811         highy_int += convy_int;
1812         highy_float += convy_float;
1813         if(highy_float > 1) {
1814             highy_float -= 1.0;
1815             highy_int++;
1816         }
1817     }
1818 }
1819
1820 static void scale_internal_ushort(GLint components, GLint widthin,
1821                            GLint heightin, const GLushort *datain,
1822                            GLint widthout, GLint heightout,
1823                            GLushort *dataout, GLint element_size,
1824                            GLint ysize, GLint group_size,
1825                            GLint myswap_bytes)
1826 {
1827     float convx;
1828     float convy;
1829     float percent;
1830     /* Max components in a format is 4, so... */
1831     float totals[4];
1832     float area;
1833     int i,j,k,xindex;
1834
1835     const char *temp, *temp0;
1836     const char *temp_index;
1837     int outindex;
1838
1839     int lowx_int, highx_int, lowy_int, highy_int;
1840     float x_percent, y_percent;
1841     float lowx_float, highx_float, lowy_float, highy_float;
1842     float convy_float, convx_float;
1843     int convy_int, convx_int;
1844     int l, m;
1845     const char *left, *right;
1846
1847     if (widthin == widthout*2 && heightin == heightout*2) {
1848         halveImage_ushort(components, widthin, heightin,
1849         (const GLushort *)datain, (GLushort *)dataout,
1850         element_size, ysize, group_size, myswap_bytes);
1851         return;
1852     }
1853     convy = (float) heightin/heightout;
1854     convx = (float) widthin/widthout;
1855     convy_int = floor(convy);
1856     convy_float = convy - convy_int;
1857     convx_int = floor(convx);
1858     convx_float = convx - convx_int;
1859
1860     area = convx * convy;
1861
1862     lowy_int = 0;
1863     lowy_float = 0;
1864     highy_int = convy_int;
1865     highy_float = convy_float;
1866
1867     for (i = 0; i < heightout; i++) {
1868         /* Clamp here to be sure we don't read beyond input buffer. */
1869         if (highy_int >= heightin)
1870             highy_int = heightin - 1;
1871         lowx_int = 0;
1872         lowx_float = 0;
1873         highx_int = convx_int;
1874         highx_float = convx_float;
1875
1876         for (j = 0; j < widthout; j++) {
1877             /*
1878             ** Ok, now apply box filter to box that goes from (lowx, lowy)
1879             ** to (highx, highy) on input data into this pixel on output
1880             ** data.
1881             */
1882             totals[0] = totals[1] = totals[2] = totals[3] = 0.0;
1883
1884             /* calculate the value for pixels in the 1st row */
1885             xindex = lowx_int*group_size;
1886             if((highy_int>lowy_int) && (highx_int>lowx_int)) {
1887
1888                 y_percent = 1-lowy_float;
1889                 temp = (const char *)datain + xindex + lowy_int * ysize;
1890                 percent = y_percent * (1-lowx_float);
1891                 for (k = 0, temp_index = temp; k < components;
1892                      k++, temp_index += element_size) {
1893                     if (myswap_bytes) {
1894                         totals[k] += __GLU_SWAP_2_BYTES(temp_index) * percent;
1895                     } else {
1896                         totals[k] += *(const GLushort*)temp_index * percent;
1897                     }
1898                 }
1899                 left = temp;
1900                 for(l = lowx_int+1; l < highx_int; l++) {
1901                     temp += group_size;
1902                     for (k = 0, temp_index = temp; k < components;
1903                          k++, temp_index += element_size) {
1904                         if (myswap_bytes) {
1905                             totals[k] +=
1906                                  __GLU_SWAP_2_BYTES(temp_index) * y_percent;
1907                         } else {
1908                             totals[k] += *(const GLushort*)temp_index * y_percent;
1909                         }
1910                     }
1911                 }
1912                 temp += group_size;
1913                 right = temp;
1914                 percent = y_percent * highx_float;
1915                 for (k = 0, temp_index = temp; k < components;
1916                      k++, temp_index += element_size) {
1917                     if (myswap_bytes) {
1918                         totals[k] += __GLU_SWAP_2_BYTES(temp_index) * percent;
1919                     } else {
1920                         totals[k] += *(const GLushort*)temp_index * percent;
1921                     }
1922                 }
1923
1924                 /* calculate the value for pixels in the last row */            
1925                 y_percent = highy_float;
1926                 percent = y_percent * (1-lowx_float);
1927                 temp = (const char *)datain + xindex + highy_int * ysize;
1928                 for (k = 0, temp_index = temp; k < components;
1929                      k++, temp_index += element_size) {
1930                     if (myswap_bytes) {
1931                         totals[k] += __GLU_SWAP_2_BYTES(temp_index) * percent;
1932                     } else {
1933                         totals[k] += *(const GLushort*)temp_index * percent;
1934                     }
1935                 }
1936                 for(l = lowx_int+1; l < highx_int; l++) {
1937                     temp += group_size;
1938                     for (k = 0, temp_index = temp; k < components;
1939                          k++, temp_index += element_size) {
1940                         if (myswap_bytes) {
1941                             totals[k] +=
1942                                  __GLU_SWAP_2_BYTES(temp_index) * y_percent;
1943                         } else {
1944                             totals[k] += *(const GLushort*)temp_index * y_percent;
1945                         }
1946                     }
1947                 }
1948                 temp += group_size;
1949                 percent = y_percent * highx_float;
1950                 for (k = 0, temp_index = temp; k < components;
1951                      k++, temp_index += element_size) {
1952                     if (myswap_bytes) {
1953                         totals[k] += __GLU_SWAP_2_BYTES(temp_index) * percent;
1954                     } else {
1955                         totals[k] += *(const GLushort*)temp_index * percent;
1956                     }
1957                 }
1958
1959                 /* calculate the value for pixels in the 1st and last column */
1960                 for(m = lowy_int+1; m < highy_int; m++) {
1961                     left += ysize;
1962                     right += ysize;
1963                     for (k = 0; k < components;
1964                          k++, left += element_size, right += element_size) {
1965                         if (myswap_bytes) {
1966                             totals[k] +=
1967                                 __GLU_SWAP_2_BYTES(left) * (1-lowx_float) +
1968                                 __GLU_SWAP_2_BYTES(right) * highx_float;
1969                         } else {
1970                             totals[k] += *(const GLushort*)left * (1-lowx_float)
1971                                        + *(const GLushort*)right * highx_float;
1972                         }
1973                     }
1974                 }
1975             } else if (highy_int > lowy_int) {
1976                 x_percent = highx_float - lowx_float;
1977                 percent = (1-lowy_float)*x_percent;
1978                 temp = (const char *)datain + xindex + lowy_int*ysize;
1979                 for (k = 0, temp_index = temp; k < components;
1980                      k++, temp_index += element_size) {
1981                     if (myswap_bytes) {
1982                         totals[k] += __GLU_SWAP_2_BYTES(temp_index) * percent;
1983                     } else {
1984                         totals[k] += *(const GLushort*)temp_index * percent;
1985                     }
1986                 }
1987                 for(m = lowy_int+1; m < highy_int; m++) {
1988                     temp += ysize;
1989                     for (k = 0, temp_index = temp; k < components;
1990                          k++, temp_index += element_size) {
1991                         if (myswap_bytes) {
1992                             totals[k] +=
1993                                 __GLU_SWAP_2_BYTES(temp_index) * x_percent;
1994                         } else {
1995                             totals[k] += *(const GLushort*)temp_index * x_percent;
1996                         }
1997                     }
1998                 }
1999                 percent = x_percent * highy_float;
2000                 temp += ysize;
2001                 for (k = 0, temp_index = temp; k < components;
2002                      k++, temp_index += element_size) {
2003                     if (myswap_bytes) {
2004                         totals[k] += __GLU_SWAP_2_BYTES(temp_index) * percent;
2005                     } else {
2006                         totals[k] += *(const GLushort*)temp_index * percent;
2007                     }
2008                 }
2009             } else if (highx_int > lowx_int) {
2010                 y_percent = highy_float - lowy_float;
2011                 percent = (1-lowx_float)*y_percent;
2012                 temp = (const char *)datain + xindex + lowy_int*ysize;
2013                 for (k = 0, temp_index = temp; k < components;
2014                      k++, temp_index += element_size) {
2015                     if (myswap_bytes) {
2016                         totals[k] += __GLU_SWAP_2_BYTES(temp_index) * percent;
2017                     } else {
2018                         totals[k] += *(const GLushort*)temp_index * percent;
2019                     }
2020                 }
2021                 for (l = lowx_int+1; l < highx_int; l++) {
2022                     temp += group_size;
2023                     for (k = 0, temp_index = temp; k < components;
2024                          k++, temp_index += element_size) {
2025                         if (myswap_bytes) {
2026                             totals[k] +=
2027                                 __GLU_SWAP_2_BYTES(temp_index) * y_percent;
2028                         } else {
2029                             totals[k] += *(const GLushort*)temp_index * y_percent;
2030                         }
2031                     }
2032                 }
2033                 temp += group_size;
2034                 percent = y_percent * highx_float;
2035                 for (k = 0, temp_index = temp; k < components;
2036                      k++, temp_index += element_size) {
2037                     if (myswap_bytes) {
2038                         totals[k] += __GLU_SWAP_2_BYTES(temp_index) * percent;
2039                     } else {
2040                         totals[k] += *(const GLushort*)temp_index * percent;
2041                     }
2042                 }
2043             } else {
2044                 percent = (highy_float-lowy_float)*(highx_float-lowx_float);
2045                 temp = (const char *)datain + xindex + lowy_int * ysize;
2046                 for (k = 0, temp_index = temp; k < components;
2047                      k++, temp_index += element_size) {
2048                     if (myswap_bytes) {
2049                         totals[k] += __GLU_SWAP_2_BYTES(temp_index) * percent;
2050                     } else {
2051                         totals[k] += *(const GLushort*)temp_index * percent;
2052                     }
2053                 }
2054             }
2055
2056             /* this is for the pixels in the body */
2057             temp0 = (const char *)datain + xindex + group_size +
2058                  (lowy_int+1)*ysize;
2059             for (m = lowy_int+1; m < highy_int; m++) {
2060                 temp = temp0;
2061                 for(l = lowx_int+1; l < highx_int; l++) {
2062                     for (k = 0, temp_index = temp; k < components;
2063                          k++, temp_index += element_size) {
2064                         if (myswap_bytes) {
2065                             totals[k] += __GLU_SWAP_2_BYTES(temp_index);
2066                         } else {
2067                             totals[k] += *(const GLushort*)temp_index;
2068                         }
2069                     }
2070                     temp += group_size;
2071                 }
2072                 temp0 += ysize;
2073             }
2074
2075             outindex = (j + (i * widthout)) * components;
2076             for (k = 0; k < components; k++) {
2077                 dataout[outindex + k] = totals[k]/area;
2078                 /*printf("totals[%d] = %f\n", k, totals[k]);*/
2079             }
2080             lowx_int = highx_int;
2081             lowx_float = highx_float;
2082             highx_int += convx_int;
2083             highx_float += convx_float;
2084             if(highx_float > 1) {
2085                 highx_float -= 1.0;
2086                 highx_int++;
2087             }
2088         }
2089         lowy_int = highy_int;
2090         lowy_float = highy_float;
2091         highy_int += convy_int;
2092         highy_float += convy_float;
2093         if(highy_float > 1) {
2094             highy_float -= 1.0;
2095             highy_int++;
2096         }
2097     }
2098 }
2099
2100 static void scale_internal_short(GLint components, GLint widthin,
2101                            GLint heightin, const GLshort *datain,
2102                            GLint widthout, GLint heightout,
2103                            GLshort *dataout, GLint element_size,
2104                            GLint ysize, GLint group_size,
2105                            GLint myswap_bytes)
2106 {
2107     float convx;
2108     float convy;
2109     float percent;
2110     /* Max components in a format is 4, so... */
2111     float totals[4];
2112     float area;
2113     int i,j,k,xindex;
2114
2115     const char *temp, *temp0;
2116     const char *temp_index;
2117     int outindex;
2118
2119     int lowx_int, highx_int, lowy_int, highy_int;
2120     float x_percent, y_percent;
2121     float lowx_float, highx_float, lowy_float, highy_float;
2122     float convy_float, convx_float;
2123     int convy_int, convx_int;
2124     int l, m;
2125     const char *left, *right;
2126
2127     GLushort swapbuf;   /* unsigned buffer */
2128
2129     if (widthin == widthout*2 && heightin == heightout*2) {
2130         halveImage_short(components, widthin, heightin,
2131         (const GLshort *)datain, (GLshort *)dataout,
2132         element_size, ysize, group_size, myswap_bytes);
2133         return;
2134     }
2135     convy = (float) heightin/heightout;
2136     convx = (float) widthin/widthout;
2137     convy_int = floor(convy);
2138     convy_float = convy - convy_int;
2139     convx_int = floor(convx);
2140     convx_float = convx - convx_int;
2141
2142     area = convx * convy;
2143
2144     lowy_int = 0;
2145     lowy_float = 0;
2146     highy_int = convy_int;
2147     highy_float = convy_float;
2148
2149     for (i = 0; i < heightout; i++) {
2150         /* Clamp here to be sure we don't read beyond input buffer. */
2151         if (highy_int >= heightin)
2152             highy_int = heightin - 1;
2153         lowx_int = 0;
2154         lowx_float = 0;
2155         highx_int = convx_int;
2156         highx_float = convx_float;
2157
2158         for (j = 0; j < widthout; j++) {
2159             /*
2160             ** Ok, now apply box filter to box that goes from (lowx, lowy)
2161             ** to (highx, highy) on input data into this pixel on output
2162             ** data.
2163             */
2164             totals[0] = totals[1] = totals[2] = totals[3] = 0.0;
2165
2166             /* calculate the value for pixels in the 1st row */
2167             xindex = lowx_int*group_size;
2168             if((highy_int>lowy_int) && (highx_int>lowx_int)) {
2169
2170                 y_percent = 1-lowy_float;
2171                 temp = (const char *)datain + xindex + lowy_int * ysize;
2172                 percent = y_percent * (1-lowx_float);
2173                 for (k = 0, temp_index = temp; k < components;
2174                      k++, temp_index += element_size) {
2175                     if (myswap_bytes) {
2176                         swapbuf = __GLU_SWAP_2_BYTES(temp_index);
2177                         totals[k] += *(const GLshort*)&swapbuf * percent;
2178                     } else {
2179                         totals[k] += *(const GLshort*)temp_index * percent;
2180                     }
2181                 }
2182                 left = temp;
2183                 for(l = lowx_int+1; l < highx_int; l++) {
2184                     temp += group_size;
2185                     for (k = 0, temp_index = temp; k < components;
2186                          k++, temp_index += element_size) {
2187                         if (myswap_bytes) {
2188                             swapbuf = __GLU_SWAP_2_BYTES(temp_index);
2189                             totals[k] += *(const GLshort*)&swapbuf * y_percent;
2190                         } else {
2191                             totals[k] += *(const GLshort*)temp_index * y_percent;
2192                         }
2193                     }
2194                 }
2195                 temp += group_size;
2196                 right = temp;
2197                 percent = y_percent * highx_float;
2198                 for (k = 0, temp_index = temp; k < components;
2199                      k++, temp_index += element_size) {
2200                     if (myswap_bytes) {
2201                         swapbuf = __GLU_SWAP_2_BYTES(temp_index);
2202                         totals[k] += *(const GLshort*)&swapbuf * percent;
2203                     } else {
2204                         totals[k] += *(const GLshort*)temp_index * percent;
2205                     }
2206                 }
2207
2208                 /* calculate the value for pixels in the last row */
2209                 y_percent = highy_float;
2210                 percent = y_percent * (1-lowx_float);
2211                 temp = (const char *)datain + xindex + highy_int * ysize;
2212                 for (k = 0, temp_index = temp; k < components;
2213                      k++, temp_index += element_size) {
2214                     if (myswap_bytes) {
2215                         swapbuf = __GLU_SWAP_2_BYTES(temp_index);
2216                         totals[k] += *(const GLshort*)&swapbuf * percent;
2217                     } else {
2218                         totals[k] += *(const GLshort*)temp_index * percent;
2219                     }
2220                 }
2221                 for(l = lowx_int+1; l < highx_int; l++) {
2222                     temp += group_size;
2223                     for (k = 0, temp_index = temp; k < components;
2224                          k++, temp_index += element_size) {
2225                         if (myswap_bytes) {
2226                             swapbuf = __GLU_SWAP_2_BYTES(temp_index);
2227                             totals[k] += *(const GLshort*)&swapbuf * y_percent;
2228                         } else {
2229                             totals[k] += *(const GLshort*)temp_index * y_percent;
2230                         }
2231                     }
2232                 }
2233                 temp += group_size;
2234                 percent = y_percent * highx_float;
2235                 for (k = 0, temp_index = temp; k < components;
2236                      k++, temp_index += element_size) {
2237                     if (myswap_bytes) {
2238                         swapbuf = __GLU_SWAP_2_BYTES(temp_index);
2239                         totals[k] += *(const GLshort*)&swapbuf * percent;
2240                     } else {
2241                         totals[k] += *(const GLshort*)temp_index * percent;
2242                     }
2243                 }
2244
2245                 /* calculate the value for pixels in the 1st and last column */
2246                 for(m = lowy_int+1; m < highy_int; m++) {
2247                     left += ysize;
2248                     right += ysize;
2249                     for (k = 0; k < components;
2250                          k++, left += element_size, right += element_size) {
2251                         if (myswap_bytes) {
2252                             swapbuf = __GLU_SWAP_2_BYTES(left);
2253                             totals[k] += *(const GLshort*)&swapbuf * (1-lowx_float);
2254                             swapbuf = __GLU_SWAP_2_BYTES(right);
2255                             totals[k] += *(const GLshort*)&swapbuf * highx_float;
2256                         } else {
2257                             totals[k] += *(const GLshort*)left * (1-lowx_float)
2258                                        + *(const GLshort*)right * highx_float;
2259                         }
2260                     }
2261                 }
2262             } else if (highy_int > lowy_int) {
2263                 x_percent = highx_float - lowx_float;
2264                 percent = (1-lowy_float)*x_percent;
2265                 temp = (const char *)datain + xindex + lowy_int*ysize;
2266                 for (k = 0, temp_index = temp; k < components;
2267                      k++, temp_index += element_size) {
2268                     if (myswap_bytes) {
2269                         swapbuf = __GLU_SWAP_2_BYTES(temp_index);
2270                         totals[k] += *(const GLshort*)&swapbuf * percent;
2271                     } else {
2272                         totals[k] += *(const GLshort*)temp_index * percent;
2273                     }
2274                 }
2275                 for(m = lowy_int+1; m < highy_int; m++) {
2276                     temp += ysize;
2277                     for (k = 0, temp_index = temp; k < components;
2278                          k++, temp_index += element_size) {
2279                         if (myswap_bytes) {
2280                             swapbuf = __GLU_SWAP_2_BYTES(temp_index);
2281                             totals[k] += *(const GLshort*)&swapbuf * x_percent;
2282                         } else {
2283                             totals[k] += *(const GLshort*)temp_index * x_percent;
2284                         }
2285                     }
2286                 }
2287                 percent = x_percent * highy_float;
2288                 temp += ysize;
2289                 for (k = 0, temp_index = temp; k < components;
2290                      k++, temp_index += element_size) {
2291                     if (myswap_bytes) {
2292                         swapbuf = __GLU_SWAP_2_BYTES(temp_index);
2293                         totals[k] += *(const GLshort*)&swapbuf * percent;
2294                     } else {
2295                         totals[k] += *(const GLshort*)temp_index * percent;
2296                     }
2297                 }
2298             } else if (highx_int > lowx_int) {
2299                 y_percent = highy_float - lowy_float;
2300                 percent = (1-lowx_float)*y_percent;
2301
2302              temp = (const char *)datain + xindex + lowy_int*ysize;
2303                 for (k = 0, temp_index = temp; k < components;
2304                      k++, temp_index += element_size) {
2305                     if (myswap_bytes) {
2306                         swapbuf = __GLU_SWAP_2_BYTES(temp_index);
2307                         totals[k] += *(const GLshort*)&swapbuf * percent;
2308                     } else {
2309                         totals[k] += *(const GLshort*)temp_index * percent;
2310                     }
2311                 }
2312                 for (l = lowx_int+1; l < highx_int; l++) {
2313                     temp += group_size;
2314                     for (k = 0, temp_index = temp; k < components;
2315                          k++, temp_index += element_size) {
2316                         if (myswap_bytes) {
2317                             swapbuf = __GLU_SWAP_2_BYTES(temp_index);
2318                             totals[k] += *(const GLshort*)&swapbuf * y_percent;
2319                         } else {
2320                             totals[k] += *(const GLshort*)temp_index * y_percent;
2321                         }
2322                     }
2323                 }
2324                 temp += group_size;
2325                 percent = y_percent * highx_float;
2326                 for (k = 0, temp_index = temp; k < components;
2327                      k++, temp_index += element_size) {
2328                     if (myswap_bytes) {
2329                         swapbuf = __GLU_SWAP_2_BYTES(temp_index);
2330                         totals[k] += *(const GLshort*)&swapbuf * percent;
2331                     } else {
2332                         totals[k] += *(const GLshort*)temp_index * percent;
2333                     }
2334                 }
2335             } else {
2336                 percent = (highy_float-lowy_float)*(highx_float-lowx_float);
2337                 temp = (const char *)datain + xindex + lowy_int * ysize;
2338                 for (k = 0, temp_index = temp; k < components;
2339                      k++, temp_index += element_size) {
2340                     if (myswap_bytes) {
2341                         swapbuf = __GLU_SWAP_2_BYTES(temp_index);
2342                         totals[k] += *(const GLshort*)&swapbuf * percent;
2343                     } else {
2344                         totals[k] += *(const GLshort*)temp_index * percent;
2345                     }
2346                 }
2347             }
2348
2349             /* this is for the pixels in the body */
2350             temp0 = (const char *)datain + xindex + group_size +
2351                  (lowy_int+1)*ysize;
2352             for (m = lowy_int+1; m < highy_int; m++) {
2353                 temp = temp0;
2354                 for(l = lowx_int+1; l < highx_int; l++) {
2355                     for (k = 0, temp_index = temp; k < components;
2356                          k++, temp_index += element_size) {
2357                         if (myswap_bytes) {
2358                             swapbuf = __GLU_SWAP_2_BYTES(temp_index);
2359                             totals[k] += *(const GLshort*)&swapbuf;
2360                         } else {
2361                             totals[k] += *(const GLshort*)temp_index;
2362                         }
2363                     }
2364                     temp += group_size;
2365                 }
2366                 temp0 += ysize;
2367             }
2368
2369             outindex = (j + (i * widthout)) * components;
2370             for (k = 0; k < components; k++) {
2371                 dataout[outindex + k] = totals[k]/area;
2372                 /*printf("totals[%d] = %f\n", k, totals[k]);*/
2373             }
2374             lowx_int = highx_int;
2375             lowx_float = highx_float;
2376             highx_int += convx_int;
2377             highx_float += convx_float;
2378             if(highx_float > 1) {
2379                 highx_float -= 1.0;
2380                 highx_int++;
2381             }
2382         }
2383         lowy_int = highy_int;
2384         lowy_float = highy_float;
2385         highy_int += convy_int;
2386         highy_float += convy_float;
2387         if(highy_float > 1) {
2388             highy_float -= 1.0;
2389             highy_int++;
2390         }
2391     }
2392 }
2393
2394 static void scale_internal_uint(GLint components, GLint widthin,
2395                            GLint heightin, const GLuint *datain,
2396                            GLint widthout, GLint heightout,
2397                            GLuint *dataout, GLint element_size,
2398                            GLint ysize, GLint group_size,
2399                            GLint myswap_bytes)
2400 {
2401     float convx;
2402     float convy;
2403     float percent;
2404     /* Max components in a format is 4, so... */
2405     float totals[4];
2406     float area;
2407     int i,j,k,xindex;
2408
2409     const char *temp, *temp0;
2410     const char *temp_index;
2411     int outindex;
2412
2413     int lowx_int, highx_int, lowy_int, highy_int;
2414     float x_percent, y_percent;
2415     float lowx_float, highx_float, lowy_float, highy_float;
2416     float convy_float, convx_float;
2417     int convy_int, convx_int;
2418     int l, m;
2419     const char *left, *right;
2420
2421     if (widthin == widthout*2 && heightin == heightout*2) {
2422         halveImage_uint(components, widthin, heightin,
2423         (const GLuint *)datain, (GLuint *)dataout,
2424         element_size, ysize, group_size, myswap_bytes);
2425         return;
2426     }
2427     convy = (float) heightin/heightout;
2428     convx = (float) widthin/widthout;
2429     convy_int = floor(convy);
2430     convy_float = convy - convy_int;
2431     convx_int = floor(convx);
2432     convx_float = convx - convx_int;
2433
2434     area = convx * convy;
2435
2436     lowy_int = 0;
2437     lowy_float = 0;
2438     highy_int = convy_int;
2439     highy_float = convy_float;
2440
2441     for (i = 0; i < heightout; i++) {
2442         /* Clamp here to be sure we don't read beyond input buffer. */
2443         if (highy_int >= heightin)
2444             highy_int = heightin - 1;
2445         lowx_int = 0;
2446         lowx_float = 0;
2447         highx_int = convx_int;
2448         highx_float = convx_float;
2449
2450         for (j = 0; j < widthout; j++) {
2451             /*
2452             ** Ok, now apply box filter to box that goes from (lowx, lowy)
2453             ** to (highx, highy) on input data into this pixel on output
2454             ** data.
2455             */
2456             totals[0] = totals[1] = totals[2] = totals[3] = 0.0;
2457
2458             /* calculate the value for pixels in the 1st row */
2459             xindex = lowx_int*group_size;
2460             if((highy_int>lowy_int) && (highx_int>lowx_int)) {
2461
2462                 y_percent = 1-lowy_float;
2463                 temp = (const char *)datain + xindex + lowy_int * ysize;
2464                 percent = y_percent * (1-lowx_float);
2465                 for (k = 0, temp_index = temp; k < components;
2466                      k++, temp_index += element_size) {
2467                     if (myswap_bytes) {
2468                         totals[k] += __GLU_SWAP_4_BYTES(temp_index) * percent;
2469                     } else {
2470                         totals[k] += *(const GLuint*)temp_index * percent;
2471                     }
2472                 }
2473                 left = temp;
2474                 for(l = lowx_int+1; l < highx_int; l++) {
2475                     temp += group_size;
2476                     for (k = 0, temp_index = temp; k < components;
2477                          k++, temp_index += element_size) {
2478                         if (myswap_bytes) {
2479                             totals[k] +=
2480                                  __GLU_SWAP_4_BYTES(temp_index) * y_percent;
2481                         } else {
2482                             totals[k] += *(const GLuint*)temp_index * y_percent;
2483                         }
2484                     }
2485                 }
2486                 temp += group_size;
2487                 right = temp;
2488                 percent = y_percent * highx_float;
2489                 for (k = 0, temp_index = temp; k < components;
2490                      k++, temp_index += element_size) {
2491                     if (myswap_bytes) {
2492                         totals[k] += __GLU_SWAP_4_BYTES(temp_index) * percent;
2493                     } else {
2494                         totals[k] += *(const GLuint*)temp_index * percent;
2495                     }
2496                 }
2497
2498                 /* calculate the value for pixels in the last row */
2499                 y_percent = highy_float;
2500                 percent = y_percent * (1-lowx_float);
2501                 temp = (const char *)datain + xindex + highy_int * ysize;
2502                 for (k = 0, temp_index = temp; k < components;
2503                      k++, temp_index += element_size) {
2504                     if (myswap_bytes) {
2505                         totals[k] += __GLU_SWAP_4_BYTES(temp_index) * percent;
2506                     } else {
2507                         totals[k] += *(const GLuint*)temp_index * percent;
2508                     }
2509                 }
2510                 for(l = lowx_int+1; l < highx_int; l++) {
2511                     temp += group_size;
2512                     for (k = 0, temp_index = temp; k < components;
2513                          k++, temp_index += element_size) {
2514                         if (myswap_bytes) {
2515                             totals[k] +=
2516                                  __GLU_SWAP_4_BYTES(temp_index) * y_percent;
2517                         } else {
2518                             totals[k] += *(const GLuint*)temp_index * y_percent;
2519                         }
2520                     }
2521                 }
2522                 temp += group_size;
2523                 percent = y_percent * highx_float;
2524                 for (k = 0, temp_index = temp; k < components;
2525                      k++, temp_index += element_size) {
2526                     if (myswap_bytes) {
2527                         totals[k] += __GLU_SWAP_4_BYTES(temp_index) * percent;
2528                     } else {
2529                         totals[k] += *(const GLuint*)temp_index * percent;
2530                     }
2531                 }
2532
2533                 /* calculate the value for pixels in the 1st and last column */
2534                 for(m = lowy_int+1; m < highy_int; m++) {
2535                     left += ysize;
2536                     right += ysize;
2537                     for (k = 0; k < components;
2538                          k++, left += element_size, right += element_size) {
2539                         if (myswap_bytes) {
2540                             totals[k] +=
2541                                 __GLU_SWAP_4_BYTES(left) * (1-lowx_float)
2542                               + __GLU_SWAP_4_BYTES(right) * highx_float;
2543                         } else {
2544                             totals[k] += *(const GLuint*)left * (1-lowx_float)
2545                                        + *(const GLuint*)right * highx_float;
2546                         }
2547                     }
2548                 }
2549             } else if (highy_int > lowy_int) {
2550                 x_percent = highx_float - lowx_float;
2551                 percent = (1-lowy_float)*x_percent;
2552                 temp = (const char *)datain + xindex + lowy_int*ysize;
2553                 for (k = 0, temp_index = temp; k < components;
2554                      k++, temp_index += element_size) {
2555                     if (myswap_bytes) {
2556                         totals[k] += __GLU_SWAP_4_BYTES(temp_index) * percent;
2557                     } else {
2558                         totals[k] += *(const GLuint*)temp_index * percent;
2559                     }
2560                 }
2561                 for(m = lowy_int+1; m < highy_int; m++) {
2562                     temp += ysize;
2563                     for (k = 0, temp_index = temp; k < components;
2564                          k++, temp_index += element_size) {
2565                         if (myswap_bytes) {
2566                             totals[k] +=
2567                                  __GLU_SWAP_4_BYTES(temp_index) * x_percent;
2568                         } else {
2569                             totals[k] += *(const GLuint*)temp_index * x_percent;
2570                         }
2571                     }
2572                 }
2573                 percent = x_percent * highy_float;
2574                 temp += ysize;
2575                 for (k = 0, temp_index = temp; k < components;
2576                      k++, temp_index += element_size) {
2577                     if (myswap_bytes) {
2578                         totals[k] += __GLU_SWAP_4_BYTES(temp_index) * percent;
2579                     } else {
2580                         totals[k] += *(const GLuint*)temp_index * percent;
2581                     }
2582                 }
2583             } else if (highx_int > lowx_int) {
2584                 y_percent = highy_float - lowy_float;
2585                 percent = (1-lowx_float)*y_percent;
2586
2587              temp = (const char *)datain + xindex + lowy_int*ysize;
2588                 for (k = 0, temp_index = temp; k < components;
2589                      k++, temp_index += element_size) {
2590                     if (myswap_bytes) {
2591                         totals[k] += __GLU_SWAP_4_BYTES(temp_index) * percent;
2592                     } else {
2593                         totals[k] += *(const GLuint*)temp_index * percent;
2594                     }
2595                 }
2596                 for (l = lowx_int+1; l < highx_int; l++) {
2597                     temp += group_size;
2598                     for (k = 0, temp_index = temp; k < components;
2599                          k++, temp_index += element_size) {
2600                         if (myswap_bytes) {
2601                             totals[k] +=
2602                                  __GLU_SWAP_4_BYTES(temp_index) * y_percent;
2603                         } else {
2604                             totals[k] += *(const GLuint*)temp_index * y_percent;
2605                         }
2606                     }
2607                 }
2608                 temp += group_size;
2609                 percent = y_percent * highx_float;
2610                 for (k = 0, temp_index = temp; k < components;
2611                      k++, temp_index += element_size) {
2612                     if (myswap_bytes) {
2613                         totals[k] += __GLU_SWAP_4_BYTES(temp_index) * percent;
2614                     } else {
2615                         totals[k] += *(const GLuint*)temp_index * percent;
2616                     }
2617                 }
2618             } else {
2619                 percent = (highy_float-lowy_float)*(highx_float-lowx_float);
2620                 temp = (const char *)datain + xindex + lowy_int * ysize;
2621                 for (k = 0, temp_index = temp; k < components;
2622                      k++, temp_index += element_size) {
2623                     if (myswap_bytes) {
2624                         totals[k] += __GLU_SWAP_4_BYTES(temp_index) * percent;
2625                     } else {
2626                         totals[k] += *(const GLuint*)temp_index * percent;
2627                     }
2628                 }
2629             }
2630
2631             /* this is for the pixels in the body */
2632             temp0 = (const char *)datain + xindex + group_size +
2633                  (lowy_int+1)*ysize;
2634             for (m = lowy_int+1; m < highy_int; m++) {
2635                 temp = temp0;
2636                 for(l = lowx_int+1; l < highx_int; l++) {
2637                     for (k = 0, temp_index = temp; k < components;
2638                          k++, temp_index += element_size) {
2639                         if (myswap_bytes) {
2640                             totals[k] += __GLU_SWAP_4_BYTES(temp_index);
2641                         } else {
2642                             totals[k] += *(const GLuint*)temp_index;
2643                         }
2644                     }
2645                     temp += group_size;
2646                 }
2647                 temp0 += ysize;
2648             }
2649
2650             outindex = (j + (i * widthout)) * components;
2651             for (k = 0; k < components; k++) {
2652                 /* clamp at UINT_MAX */
2653                 float value= totals[k]/area;
2654                 if (value >= (float) UINT_MAX) {        /* need '=' */
2655                   dataout[outindex + k] = UINT_MAX;
2656                 }
2657                 else dataout[outindex + k] = value;
2658             }
2659             lowx_int = highx_int;
2660             lowx_float = highx_float;
2661             highx_int += convx_int;
2662             highx_float += convx_float;
2663             if(highx_float > 1) {
2664                 highx_float -= 1.0;
2665                 highx_int++;
2666             }
2667         }
2668         lowy_int = highy_int;
2669         lowy_float = highy_float;
2670         highy_int += convy_int;
2671         highy_float += convy_float;
2672         if(highy_float > 1) {
2673             highy_float -= 1.0;
2674             highy_int++;
2675         }
2676     }
2677 }
2678
2679
2680
2681 static void scale_internal_int(GLint components, GLint widthin,
2682                            GLint heightin, const GLint *datain,
2683                            GLint widthout, GLint heightout,
2684                            GLint *dataout, GLint element_size,
2685                            GLint ysize, GLint group_size,
2686                            GLint myswap_bytes)
2687 {
2688     float convx;
2689     float convy;
2690     float percent;
2691     /* Max components in a format is 4, so... */
2692     float totals[4];
2693     float area;
2694     int i,j,k,xindex;
2695
2696     const char *temp, *temp0;
2697     const char *temp_index;
2698     int outindex;
2699
2700     int lowx_int, highx_int, lowy_int, highy_int;
2701     float x_percent, y_percent;
2702     float lowx_float, highx_float, lowy_float, highy_float;
2703     float convy_float, convx_float;
2704     int convy_int, convx_int;
2705     int l, m;
2706     const char *left, *right;
2707
2708     GLuint swapbuf;     /* unsigned buffer */
2709
2710     if (widthin == widthout*2 && heightin == heightout*2) {
2711         halveImage_int(components, widthin, heightin,
2712         (const GLint *)datain, (GLint *)dataout,
2713         element_size, ysize, group_size, myswap_bytes);
2714         return;
2715     }
2716     convy = (float) heightin/heightout;
2717     convx = (float) widthin/widthout;
2718     convy_int = floor(convy);
2719     convy_float = convy - convy_int;
2720     convx_int = floor(convx);
2721     convx_float = convx - convx_int;
2722
2723     area = convx * convy;
2724
2725     lowy_int = 0;
2726     lowy_float = 0;
2727     highy_int = convy_int;
2728     highy_float = convy_float;
2729
2730     for (i = 0; i < heightout; i++) {
2731         /* Clamp here to be sure we don't read beyond input buffer. */
2732         if (highy_int >= heightin)
2733             highy_int = heightin - 1;
2734         lowx_int = 0;
2735         lowx_float = 0;
2736         highx_int = convx_int;
2737         highx_float = convx_float;
2738
2739         for (j = 0; j < widthout; j++) {
2740             /*
2741             ** Ok, now apply box filter to box that goes from (lowx, lowy)
2742             ** to (highx, highy) on input data into this pixel on output
2743             ** data.
2744             */
2745             totals[0] = totals[1] = totals[2] = totals[3] = 0.0;
2746
2747             /* calculate the value for pixels in the 1st row */
2748             xindex = lowx_int*group_size;
2749             if((highy_int>lowy_int) && (highx_int>lowx_int)) {
2750
2751                 y_percent = 1-lowy_float;
2752                 temp = (const char *)datain + xindex + lowy_int * ysize;
2753                 percent = y_percent * (1-lowx_float);
2754                 for (k = 0, temp_index = temp; k < components;
2755                      k++, temp_index += element_size) {
2756                     if (myswap_bytes) {
2757                         swapbuf = __GLU_SWAP_4_BYTES(temp_index);
2758                         totals[k] += *(const GLint*)&swapbuf * percent;
2759                     } else {
2760                         totals[k] += *(const GLint*)temp_index * percent;
2761                     }
2762                 }
2763                 left = temp;
2764                 for(l = lowx_int+1; l < highx_int; l++) {
2765                     temp += group_size;
2766                     for (k = 0, temp_index = temp; k < components;
2767                          k++, temp_index += element_size) {
2768                         if (myswap_bytes) {
2769                             swapbuf = __GLU_SWAP_4_BYTES(temp_index);
2770                             totals[k] += *(const GLint*)&swapbuf * y_percent;
2771                         } else {
2772                             totals[k] += *(const GLint*)temp_index * y_percent;
2773                         }
2774                     }
2775                 }
2776                 temp += group_size;
2777                 right = temp;
2778                 percent = y_percent * highx_float;
2779                 for (k = 0, temp_index = temp; k < components;
2780                      k++, temp_index += element_size) {
2781                     if (myswap_bytes) {
2782                         swapbuf = __GLU_SWAP_4_BYTES(temp_index);
2783                         totals[k] += *(const GLint*)&swapbuf * percent;
2784                     } else {
2785                         totals[k] += *(const GLint*)temp_index * percent;
2786                     }
2787                 }
2788
2789                 /* calculate the value for pixels in the last row */
2790                 y_percent = highy_float;
2791                 percent = y_percent * (1-lowx_float);
2792                 temp = (const char *)datain + xindex + highy_int * ysize;
2793                 for (k = 0, temp_index = temp; k < components;
2794                      k++, temp_index += element_size) {
2795                     if (myswap_bytes) {
2796                         swapbuf = __GLU_SWAP_4_BYTES(temp_index);
2797                         totals[k] += *(const GLint*)&swapbuf  * percent;
2798                     } else {
2799                         totals[k] += *(const GLint*)temp_index * percent;
2800                     }
2801                 }
2802                 for(l = lowx_int+1; l < highx_int; l++) {
2803                     temp += group_size;
2804                     for (k = 0, temp_index = temp; k < components;
2805                          k++, temp_index += element_size) {
2806                         if (myswap_bytes) {
2807                             swapbuf = __GLU_SWAP_4_BYTES(temp_index);
2808                             totals[k] += *(const GLint*)&swapbuf * y_percent;
2809                         } else {
2810                             totals[k] += *(const GLint*)temp_index * y_percent;
2811                         }
2812                     }
2813                 }
2814                 temp += group_size;
2815                 percent = y_percent * highx_float;
2816                 for (k = 0, temp_index = temp; k < components;
2817                      k++, temp_index += element_size) {
2818                     if (myswap_bytes) {
2819                         swapbuf = __GLU_SWAP_4_BYTES(temp_index);
2820                         totals[k] += *(const GLint*)&swapbuf * percent;
2821                     } else {
2822                         totals[k] += *(const GLint*)temp_index * percent;
2823                     }
2824                 }
2825
2826                 /* calculate the value for pixels in the 1st and last column */
2827                 for(m = lowy_int+1; m < highy_int; m++) {
2828                     left += ysize;
2829                     right += ysize;
2830                     for (k = 0; k < components;
2831                          k++, left += element_size, right += element_size) {
2832                         if (myswap_bytes) {
2833                             swapbuf = __GLU_SWAP_4_BYTES(left);
2834                             totals[k] += *(const GLint*)&swapbuf * (1-lowx_float);
2835                             swapbuf = __GLU_SWAP_4_BYTES(right);
2836                             totals[k] += *(const GLint*)&swapbuf * highx_float;
2837                         } else {
2838                             totals[k] += *(const GLint*)left * (1-lowx_float)
2839                                        + *(const GLint*)right * highx_float;
2840                         }
2841                     }
2842                 }
2843             } else if (highy_int > lowy_int) {
2844                 x_percent = highx_float - lowx_float;
2845                 percent = (1-lowy_float)*x_percent;
2846                 temp = (const char *)datain + xindex + lowy_int*ysize;
2847                 for (k = 0, temp_index = temp; k < components;
2848                      k++, temp_index += element_size) {
2849                     if (myswap_bytes) {
2850                         swapbuf = __GLU_SWAP_4_BYTES(temp_index);
2851                         totals[k] += *(const GLint*)&swapbuf * percent;
2852                     } else {
2853                         totals[k] += *(const GLint*)temp_index * percent;
2854                     }
2855                 }
2856                 for(m = lowy_int+1; m < highy_int; m++) {
2857                     temp += ysize;
2858                     for (k = 0, temp_index = temp; k < components;
2859                          k++, temp_index += element_size) {
2860                         if (myswap_bytes) {
2861                             swapbuf = __GLU_SWAP_4_BYTES(temp_index);
2862                             totals[k] += *(const GLint*)&swapbuf * x_percent;
2863                         } else {
2864                             totals[k] += *(const GLint*)temp_index * x_percent;
2865                         }
2866                     }
2867                 }
2868                 percent = x_percent * highy_float;
2869                 temp += ysize;
2870                 for (k = 0, temp_index = temp; k < components;
2871                      k++, temp_index += element_size) {
2872                     if (myswap_bytes) {
2873                         swapbuf = __GLU_SWAP_4_BYTES(temp_index);
2874                         totals[k] += *(const GLint*)&swapbuf * percent;
2875                     } else {
2876                         totals[k] += *(const GLint*)temp_index * percent;
2877                     }
2878                 }
2879             } else if (highx_int > lowx_int) {
2880                 y_percent = highy_float - lowy_float;
2881                 percent = (1-lowx_float)*y_percent;
2882
2883                  temp = (const char *)datain + xindex + lowy_int*ysize;
2884                 for (k = 0, temp_index = temp; k < components;
2885                      k++, temp_index += element_size) {
2886                     if (myswap_bytes) {
2887                         swapbuf = __GLU_SWAP_4_BYTES(temp_index);
2888                         totals[k] += *(const GLint*)&swapbuf * percent;
2889                     } else {
2890                         totals[k] += *(const GLint*)temp_index * percent;
2891                     }
2892                 }
2893                 for (l = lowx_int+1; l < highx_int; l++) {
2894                     temp += group_size;
2895                     for (k = 0, temp_index = temp; k < components;
2896                          k++, temp_index += element_size) {
2897                         if (myswap_bytes) {
2898                             swapbuf = __GLU_SWAP_4_BYTES(temp_index);
2899                             totals[k] += *(const GLint*)&swapbuf * y_percent;
2900                         } else {
2901                             totals[k] += *(const GLint*)temp_index * y_percent;
2902                         }
2903                     }
2904                 }
2905                 temp += group_size;
2906                 percent = y_percent * highx_float;
2907                 for (k = 0, temp_index = temp; k < components;
2908                      k++, temp_index += element_size) {
2909                     if (myswap_bytes) {
2910                         swapbuf = __GLU_SWAP_4_BYTES(temp_index);
2911                         totals[k] += *(const GLint*)&swapbuf * percent;
2912                     } else {
2913                         totals[k] += *(const GLint*)temp_index * percent;
2914                     }
2915                 }
2916             } else {
2917                 percent = (highy_float-lowy_float)*(highx_float-lowx_float);
2918                 temp = (const char *)datain + xindex + lowy_int * ysize;
2919                 for (k = 0, temp_index = temp; k < components;
2920                      k++, temp_index += element_size) {
2921                     if (myswap_bytes) {
2922                         swapbuf = __GLU_SWAP_4_BYTES(temp_index);
2923                         totals[k] += *(const GLint*)&swapbuf * percent;
2924                     } else {
2925                         totals[k] += *(const GLint*)temp_index * percent;
2926                     }
2927                 }
2928             }
2929
2930             /* this is for the pixels in the body */
2931             temp0 = (const char *)datain + xindex + group_size +
2932                  (lowy_int+1)*ysize;
2933             for (m = lowy_int+1; m < highy_int; m++) {
2934                 temp = temp0;
2935                 for(l = lowx_int+1; l < highx_int; l++) {
2936                     for (k = 0, temp_index = temp; k < components;
2937                          k++, temp_index += element_size) {
2938                         if (myswap_bytes) {
2939                             swapbuf = __GLU_SWAP_4_BYTES(temp_index);
2940                             totals[k] += *(const GLint*)&swapbuf;
2941                         } else {
2942                             totals[k] += *(const GLint*)temp_index;
2943                         }
2944                     }
2945                     temp += group_size;
2946                 }
2947                 temp0 += ysize;
2948             }
2949
2950             outindex = (j + (i * widthout)) * components;
2951             for (k = 0; k < components; k++) {
2952                 dataout[outindex + k] = totals[k]/area;
2953                 /*printf("totals[%d] = %f\n", k, totals[k]);*/
2954             }
2955             lowx_int = highx_int;
2956             lowx_float = highx_float;
2957             highx_int += convx_int;
2958             highx_float += convx_float;
2959             if(highx_float > 1) {
2960                 highx_float -= 1.0;
2961                 highx_int++;
2962             }
2963         }
2964         lowy_int = highy_int;
2965         lowy_float = highy_float;
2966         highy_int += convy_int;
2967         highy_float += convy_float;
2968         if(highy_float > 1) {
2969             highy_float -= 1.0;
2970             highy_int++;
2971         }
2972     }
2973 }
2974
2975
2976
2977 static void scale_internal_float(GLint components, GLint widthin,
2978                            GLint heightin, const GLfloat *datain,
2979                            GLint widthout, GLint heightout,
2980                            GLfloat *dataout, GLint element_size,
2981                            GLint ysize, GLint group_size,
2982                            GLint myswap_bytes)
2983 {
2984     float convx;
2985     float convy;
2986     float percent;
2987     /* Max components in a format is 4, so... */
2988     float totals[4];
2989     float area;
2990     int i,j,k,xindex;
2991
2992     const char *temp, *temp0;
2993     const char *temp_index;
2994     int outindex;
2995
2996     int lowx_int, highx_int, lowy_int, highy_int;
2997     float x_percent, y_percent;
2998     float lowx_float, highx_float, lowy_float, highy_float;
2999     float convy_float, convx_float;
3000     int convy_int, convx_int;
3001     int l, m;
3002     const char *left, *right;
3003
3004     union { GLuint b; GLfloat f; } swapbuf;
3005
3006     if (widthin == widthout*2 && heightin == heightout*2) {
3007         halveImage_float(components, widthin, heightin,
3008         (const GLfloat *)datain, (GLfloat *)dataout,
3009         element_size, ysize, group_size, myswap_bytes);
3010         return;
3011     }
3012     convy = (float) heightin/heightout;
3013     convx = (float) widthin/widthout;
3014     convy_int = floor(convy);
3015     convy_float = convy - convy_int;
3016     convx_int = floor(convx);
3017     convx_float = convx - convx_int;
3018
3019     area = convx * convy;
3020
3021     lowy_int = 0;
3022     lowy_float = 0;
3023     highy_int = convy_int;
3024     highy_float = convy_float;
3025
3026     for (i = 0; i < heightout; i++) {
3027         /* Clamp here to be sure we don't read beyond input buffer. */
3028         if (highy_int >= heightin)
3029             highy_int = heightin - 1;
3030         lowx_int = 0;
3031         lowx_float = 0;
3032         highx_int = convx_int;
3033         highx_float = convx_float;
3034
3035         for (j = 0; j < widthout; j++) {
3036             /*
3037             ** Ok, now apply box filter to box that goes from (lowx, lowy)
3038             ** to (highx, highy) on input data into this pixel on output
3039             ** data.
3040             */
3041             totals[0] = totals[1] = totals[2] = totals[3] = 0.0;
3042
3043             /* calculate the value for pixels in the 1st row */
3044             xindex = lowx_int*group_size;
3045             if((highy_int>lowy_int) && (highx_int>lowx_int)) {
3046
3047                 y_percent = 1-lowy_float;
3048                 temp = (const char *)datain + xindex + lowy_int * ysize;
3049                 percent = y_percent * (1-lowx_float);
3050                 for (k = 0, temp_index = temp; k < components;
3051                      k++, temp_index += element_size) {
3052                     if (myswap_bytes) {
3053                         swapbuf.b = __GLU_SWAP_4_BYTES(temp_index);
3054                         totals[k] += swapbuf.f * percent;
3055                     } else {
3056                         totals[k] += *(const GLfloat*)temp_index * percent;
3057                     }
3058                 }
3059                 left = temp;
3060                 for(l = lowx_int+1; l < highx_int; l++) {
3061                     temp += group_size;
3062                     for (k = 0, temp_index = temp; k < components;
3063                          k++, temp_index += element_size) {
3064                         if (myswap_bytes) {
3065                             swapbuf.b = __GLU_SWAP_4_BYTES(temp_index);
3066                             totals[k] += swapbuf.f * y_percent;
3067                         } else {
3068                             totals[k] += *(const GLfloat*)temp_index * y_percent;
3069                         }
3070                     }
3071                 }
3072                 temp += group_size;
3073                 right = temp;
3074                 percent = y_percent * highx_float;
3075                 for (k = 0, temp_index = temp; k < components;
3076                      k++, temp_index += element_size) {
3077                     if (myswap_bytes) {
3078                         swapbuf.b = __GLU_SWAP_4_BYTES(temp_index);
3079                         totals[k] += swapbuf.f * percent;
3080                     } else {
3081                         totals[k] += *(const GLfloat*)temp_index * percent;
3082                     }
3083                 }
3084
3085                 /* calculate the value for pixels in the last row */
3086                 y_percent = highy_float;
3087                 percent = y_percent * (1-lowx_float);
3088                 temp = (const char *)datain + xindex + highy_int * ysize;
3089                 for (k = 0, temp_index = temp; k < components;
3090                      k++, temp_index += element_size) {
3091                     if (myswap_bytes) {
3092                         swapbuf.b = __GLU_SWAP_4_BYTES(temp_index);
3093                         totals[k] += swapbuf.f * percent;
3094                     } else {
3095                         totals[k] += *(const GLfloat*)temp_index * percent;
3096                     }
3097                 }
3098                 for(l = lowx_int+1; l < highx_int; l++) {
3099                     temp += group_size;
3100                     for (k = 0, temp_index = temp; k < components;
3101                          k++, temp_index += element_size) {
3102                         if (myswap_bytes) {
3103                             swapbuf.b = __GLU_SWAP_4_BYTES(temp_index);
3104                             totals[k] += swapbuf.f * y_percent;
3105                         } else {
3106                             totals[k] += *(const GLfloat*)temp_index * y_percent;
3107                         }
3108                     }
3109                 }
3110                 temp += group_size;
3111                 percent = y_percent * highx_float;
3112                 for (k = 0, temp_index = temp; k < components;
3113                      k++, temp_index += element_size) {
3114                     if (myswap_bytes) {
3115                         swapbuf.b = __GLU_SWAP_4_BYTES(temp_index);
3116                         totals[k] += swapbuf.f * percent;
3117                     } else {
3118                         totals[k] += *(const GLfloat*)temp_index * percent;
3119                     }
3120                 }
3121
3122                 /* calculate the value for pixels in the 1st and last column */
3123                 for(m = lowy_int+1; m < highy_int; m++) {
3124                     left += ysize;
3125                     right += ysize;
3126                     for (k = 0; k < components;
3127                          k++, left += element_size, right += element_size) {
3128                         if (myswap_bytes) {
3129                             swapbuf.b = __GLU_SWAP_4_BYTES(left);
3130                             totals[k] += swapbuf.f * (1-lowx_float);
3131                             swapbuf.b = __GLU_SWAP_4_BYTES(right);
3132                             totals[k] += swapbuf.f * highx_float;
3133                         } else {
3134                             totals[k] += *(const GLfloat*)left * (1-lowx_float)
3135                                        + *(const GLfloat*)right * highx_float;
3136                         }
3137                     }
3138                 }
3139             } else if (highy_int > lowy_int) {
3140                 x_percent = highx_float - lowx_float;
3141                 percent = (1-lowy_float)*x_percent;
3142                 temp = (const char *)datain + xindex + lowy_int*ysize;
3143                 for (k = 0, temp_index = temp; k < components;
3144                      k++, temp_index += element_size) {
3145                     if (myswap_bytes) {
3146                         swapbuf.b = __GLU_SWAP_4_BYTES(temp_index);
3147                         totals[k] += swapbuf.f * percent;
3148                     } else {
3149                         totals[k] += *(const GLfloat*)temp_index * percent;
3150                     }
3151                 }
3152                 for(m = lowy_int+1; m < highy_int; m++) {
3153                     temp += ysize;
3154                     for (k = 0, temp_index = temp; k < components;
3155                          k++, temp_index += element_size) {
3156                         if (myswap_bytes) {
3157                             swapbuf.b = __GLU_SWAP_4_BYTES(temp_index);
3158                             totals[k] += swapbuf.f * x_percent;
3159                         } else {
3160                             totals[k] += *(const GLfloat*)temp_index * x_percent;
3161                         }
3162                     }
3163                 }
3164                 percent = x_percent * highy_float;
3165                 temp += ysize;
3166                 for (k = 0, temp_index = temp; k < components;
3167                      k++, temp_index += element_size) {
3168                     if (myswap_bytes) {
3169                         swapbuf.b = __GLU_SWAP_4_BYTES(temp_index);
3170                         totals[k] += swapbuf.f * percent;
3171                     } else {
3172                         totals[k] += *(const GLfloat*)temp_index * percent;
3173                     }
3174                 }
3175             } else if (highx_int > lowx_int) {
3176                 y_percent = highy_float - lowy_float;
3177                 percent = (1-lowx_float)*y_percent;
3178
3179              temp = (const char *)datain + xindex + lowy_int*ysize;
3180                 for (k = 0, temp_index = temp; k < components;
3181                      k++, temp_index += element_size) {
3182                     if (myswap_bytes) {
3183                         swapbuf.b = __GLU_SWAP_4_BYTES(temp_index);
3184                         totals[k] += swapbuf.f * percent;
3185                     } else {
3186                         totals[k] += *(const GLfloat*)temp_index * percent;
3187                     }
3188                 }
3189                 for (l = lowx_int+1; l < highx_int; l++) {
3190                     temp += group_size;
3191                     for (k = 0, temp_index = temp; k < components;
3192                          k++, temp_index += element_size) {
3193                         if (myswap_bytes) {
3194                             swapbuf.b = __GLU_SWAP_4_BYTES(temp_index);
3195                             totals[k] += swapbuf.f * y_percent;
3196                         } else {
3197                             totals[k] += *(const GLfloat*)temp_index * y_percent;
3198                         }
3199                     }
3200                 }
3201                 temp += group_size;
3202                 percent = y_percent * highx_float;
3203                 for (k = 0, temp_index = temp; k < components;
3204                      k++, temp_index += element_size) {
3205                     if (myswap_bytes) {
3206                         swapbuf.b = __GLU_SWAP_4_BYTES(temp_index);
3207                         totals[k] += swapbuf.f * percent;
3208                     } else {
3209                         totals[k] += *(const GLfloat*)temp_index * percent;
3210                     }
3211                 }
3212             } else {
3213                 percent = (highy_float-lowy_float)*(highx_float-lowx_float);
3214                 temp = (const char *)datain + xindex + lowy_int * ysize;
3215                 for (k = 0, temp_index = temp; k < components;
3216                      k++, temp_index += element_size) {
3217                     if (myswap_bytes) {
3218                         swapbuf.b = __GLU_SWAP_4_BYTES(temp_index);
3219                         totals[k] += swapbuf.f * percent;
3220                     } else {
3221                         totals[k] += *(const GLfloat*)temp_index * percent;
3222                     }
3223                 }
3224             }
3225
3226             /* this is for the pixels in the body */
3227             temp0 = (const char *)datain + xindex + group_size +
3228                  (lowy_int+1)*ysize;
3229             for (m = lowy_int+1; m < highy_int; m++) {
3230                 temp = temp0;
3231                 for(l = lowx_int+1; l < highx_int; l++) {
3232                     for (k = 0, temp_index = temp; k < components;
3233                          k++, temp_index += element_size) {
3234                         if (myswap_bytes) {
3235                             swapbuf.b = __GLU_SWAP_4_BYTES(temp_index);
3236                             totals[k] += swapbuf.f;
3237                         } else {
3238                             totals[k] += *(const GLfloat*)temp_index;
3239                         }
3240                     }
3241                     temp += group_size;
3242                 }
3243                 temp0 += ysize;
3244             }
3245
3246             outindex = (j + (i * widthout)) * components;
3247             for (k = 0; k < components; k++) {
3248                 dataout[outindex + k] = totals[k]/area;
3249                 /*printf("totals[%d] = %f\n", k, totals[k]);*/
3250             }
3251             lowx_int = highx_int;
3252             lowx_float = highx_float;
3253             highx_int += convx_int;
3254             highx_float += convx_float;
3255             if(highx_float > 1) {
3256                 highx_float -= 1.0;
3257                 highx_int++;
3258             }
3259         }
3260         lowy_int = highy_int;
3261         lowy_float = highy_float;
3262         highy_int += convy_int;
3263         highy_float += convy_float;
3264         if(highy_float > 1) {
3265             highy_float -= 1.0;
3266             highy_int++;
3267         }
3268     }
3269 }
3270
3271 static int checkMipmapArgs(GLenum internalFormat, GLenum format, GLenum type)
3272 {
3273     if (!legalFormat(format) || !legalType(type)) {
3274         return GLU_INVALID_ENUM;
3275     }
3276     if (format == GL_STENCIL_INDEX) {
3277         return GLU_INVALID_ENUM;
3278     }
3279
3280     if (!isLegalFormatForPackedPixelType(format, type)) {
3281         return GLU_INVALID_OPERATION;
3282     }
3283
3284     return 0;
3285 } /* checkMipmapArgs() */
3286
3287 static GLboolean legalFormat(GLenum format)
3288 {
3289     switch(format) {
3290       case GL_COLOR_INDEX:
3291       case GL_STENCIL_INDEX:
3292       case GL_DEPTH_COMPONENT:
3293       case GL_RED:
3294       case GL_GREEN:
3295       case GL_BLUE:
3296       case GL_ALPHA:
3297       case GL_RGB:
3298       case GL_RGBA:
3299       case GL_LUMINANCE:
3300       case GL_LUMINANCE_ALPHA:
3301       case GL_BGR:
3302       case GL_BGRA:
3303         return GL_TRUE;
3304       default:
3305         return GL_FALSE;
3306     }
3307 }
3308
3309
3310 static GLboolean legalType(GLenum type)
3311 {
3312     switch(type) {
3313       case GL_BITMAP:
3314       case GL_BYTE:
3315       case GL_UNSIGNED_BYTE:
3316       case GL_SHORT:
3317       case GL_UNSIGNED_SHORT:
3318       case GL_INT:
3319       case GL_UNSIGNED_INT:
3320       case GL_FLOAT:
3321       case GL_UNSIGNED_BYTE_3_3_2:
3322       case GL_UNSIGNED_BYTE_2_3_3_REV:  
3323       case GL_UNSIGNED_SHORT_5_6_5:
3324       case GL_UNSIGNED_SHORT_5_6_5_REV:
3325       case GL_UNSIGNED_SHORT_4_4_4_4:
3326       case GL_UNSIGNED_SHORT_4_4_4_4_REV:
3327       case GL_UNSIGNED_SHORT_5_5_5_1:
3328       case GL_UNSIGNED_SHORT_1_5_5_5_REV:
3329       case GL_UNSIGNED_INT_8_8_8_8:
3330       case GL_UNSIGNED_INT_8_8_8_8_REV:
3331       case GL_UNSIGNED_INT_10_10_10_2:
3332       case GL_UNSIGNED_INT_2_10_10_10_REV:
3333          return GL_TRUE;
3334       default:
3335         return GL_FALSE;
3336     }
3337 }
3338
3339 /* */
3340 static GLboolean isTypePackedPixel(GLenum type)
3341 {
3342    assert(legalType(type));
3343
3344    if (type == GL_UNSIGNED_BYTE_3_3_2 ||
3345        type == GL_UNSIGNED_BYTE_2_3_3_REV ||
3346        type == GL_UNSIGNED_SHORT_5_6_5 ||
3347        type == GL_UNSIGNED_SHORT_5_6_5_REV ||
3348        type == GL_UNSIGNED_SHORT_4_4_4_4 ||
3349        type == GL_UNSIGNED_SHORT_4_4_4_4_REV ||
3350        type == GL_UNSIGNED_SHORT_5_5_5_1 ||
3351        type == GL_UNSIGNED_SHORT_1_5_5_5_REV ||
3352        type == GL_UNSIGNED_INT_8_8_8_8 ||
3353        type == GL_UNSIGNED_INT_8_8_8_8_REV ||
3354        type == GL_UNSIGNED_INT_10_10_10_2 ||
3355        type == GL_UNSIGNED_INT_2_10_10_10_REV) {
3356       return 1;
3357    }
3358    else return 0;
3359 } /* isTypePackedPixel() */
3360
3361 /* Determines if the packed pixel type is compatible with the format */
3362 static GLboolean isLegalFormatForPackedPixelType(GLenum format, GLenum type)
3363 {
3364    /* if not a packed pixel type then return true */
3365    if (!isTypePackedPixel(type)) {
3366       return GL_TRUE;
3367    }
3368
3369    /* 3_3_2/2_3_3_REV & 5_6_5/5_6_5_REV are only compatible with RGB */
3370    if ((type == GL_UNSIGNED_BYTE_3_3_2 || type == GL_UNSIGNED_BYTE_2_3_3_REV||
3371         type == GL_UNSIGNED_SHORT_5_6_5|| type == GL_UNSIGNED_SHORT_5_6_5_REV)
3372        && format != GL_RGB)
3373       return GL_FALSE;
3374
3375    /* 4_4_4_4/4_4_4_4_REV & 5_5_5_1/1_5_5_5_REV & 8_8_8_8/8_8_8_8_REV &
3376     * 10_10_10_2/2_10_10_10_REV are only compatible with RGBA, BGRA & ABGR_EXT.
3377     */
3378    if ((type == GL_UNSIGNED_SHORT_4_4_4_4 ||
3379         type == GL_UNSIGNED_SHORT_4_4_4_4_REV ||
3380         type == GL_UNSIGNED_SHORT_5_5_5_1 ||
3381         type == GL_UNSIGNED_SHORT_1_5_5_5_REV ||
3382         type == GL_UNSIGNED_INT_8_8_8_8 ||
3383         type == GL_UNSIGNED_INT_8_8_8_8_REV ||
3384         type == GL_UNSIGNED_INT_10_10_10_2 ||
3385         type == GL_UNSIGNED_INT_2_10_10_10_REV) &&
3386        (format != GL_RGBA &&
3387         format != GL_BGRA)) {
3388       return GL_FALSE;
3389    }
3390
3391    return GL_TRUE;
3392 } /* isLegalFormatForPackedPixelType() */
3393
3394 static GLboolean isLegalLevels(GLint userLevel,GLint baseLevel,GLint maxLevel,
3395                                GLint totalLevels)
3396 {
3397    if (baseLevel < 0 || baseLevel < userLevel || maxLevel < baseLevel ||
3398        totalLevels < maxLevel)
3399       return GL_FALSE;
3400    else return GL_TRUE;
3401 } /* isLegalLevels() */
3402
3403 /* Given user requested texture size, determine if it fits. If it
3404  * doesn't then halve both sides and make the determination again
3405  * until it does fit (for IR only).
3406  * Note that proxy textures are not implemented in RE* even though
3407  * they advertise the texture extension.
3408  * Note that proxy textures are implemented but not according to spec in
3409  * IMPACT*.
3410  */
3411 static void closestFit(GLenum target, GLint width, GLint height,
3412                        GLint internalFormat, GLenum format, GLenum type,
3413                        GLint *newWidth, GLint *newHeight)
3414 {
3415    /* Use proxy textures if OpenGL version is >= 1.1 */
3416    if ( (strtod((const char *)glGetString(GL_VERSION),NULL) >= 1.1)
3417         ) {
3418       GLint widthPowerOf2= nearestPower(width);
3419       GLint heightPowerOf2= nearestPower(height);       
3420       GLint proxyWidth;
3421
3422       do {
3423          /* compute level 1 width & height, clamping each at 1 */
3424          GLint widthAtLevelOne= (widthPowerOf2 > 1) ?
3425                                  widthPowerOf2 >> 1 :
3426                                  widthPowerOf2;
3427          GLint heightAtLevelOne= (heightPowerOf2 > 1) ?
3428                                   heightPowerOf2 >> 1 :
3429                                   heightPowerOf2;
3430          GLenum proxyTarget;
3431          assert(widthAtLevelOne > 0); assert(heightAtLevelOne > 0);
3432
3433          /* does width x height at level 1 & all their mipmaps fit? */
3434          if (target == GL_TEXTURE_2D || target == GL_PROXY_TEXTURE_2D) {
3435             proxyTarget = GL_PROXY_TEXTURE_2D;
3436             glTexImage2D(proxyTarget, 1, /* must be non-zero */
3437                          internalFormat,
3438                          widthAtLevelOne,heightAtLevelOne,0,format,type,NULL);
3439          } else
3440 #if defined(GL_ARB_texture_cube_map)
3441          if ((target == GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB) ||
3442              (target == GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB) ||
3443              (target == GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB) ||
3444              (target == GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB) ||
3445              (target == GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB) ||
3446              (target == GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB)) {
3447              proxyTarget = GL_PROXY_TEXTURE_CUBE_MAP_ARB;
3448              glTexImage2D(proxyTarget, 1, /* must be non-zero */
3449                           internalFormat,
3450                           widthAtLevelOne,heightAtLevelOne,0,format,type,NULL);
3451          } else
3452 #endif /* GL_ARB_texture_cube_map */
3453          {
3454             assert(target == GL_TEXTURE_1D || target == GL_PROXY_TEXTURE_1D);
3455             proxyTarget = GL_PROXY_TEXTURE_1D;
3456             glTexImage1D(proxyTarget, 1, /* must be non-zero */
3457                          internalFormat,widthAtLevelOne,0,format,type,NULL);
3458          }
3459          glGetTexLevelParameteriv(proxyTarget, 1,GL_TEXTURE_WIDTH,&proxyWidth);
3460          /* does it fit??? */
3461          if (proxyWidth == 0) { /* nope, so try again with these sizes */
3462             if (widthPowerOf2 == 1 && heightPowerOf2 == 1) {
3463                /* An 1x1 texture couldn't fit for some reason, so
3464                 * break out.  This should never happen. But things
3465                 * happen.  The disadvantage with this if-statement is
3466                 * that we will never be aware of when this happens
3467                 * since it will silently branch out.
3468                 */
3469                goto noProxyTextures;
3470             }
3471             widthPowerOf2= widthAtLevelOne;
3472             heightPowerOf2= heightAtLevelOne;
3473          }
3474          /* else it does fit */
3475       } while (proxyWidth == 0);
3476       /* loop must terminate! */
3477
3478       /* return the width & height at level 0 that fits */
3479       *newWidth= widthPowerOf2;
3480       *newHeight= heightPowerOf2;
3481 /*printf("Proxy Textures\n");*/
3482    } /* if gluCheckExtension() */
3483    else {                       /* no texture extension, so do this instead */
3484       GLint maxsize;
3485
3486 noProxyTextures:
3487
3488       glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxsize);
3489       /* clamp user's texture sizes to maximum sizes, if necessary */
3490       *newWidth = nearestPower(width);
3491       if (*newWidth > maxsize) *newWidth = maxsize;
3492       *newHeight = nearestPower(height);
3493       if (*newHeight > maxsize) *newHeight = maxsize;
3494 /*printf("NO proxy textures\n");*/
3495    }
3496 } /* closestFit() */
3497
3498 GLint GLAPIENTRY
3499 gluScaleImage(GLenum format, GLsizei widthin, GLsizei heightin,
3500                     GLenum typein, const void *datain,
3501                     GLsizei widthout, GLsizei heightout, GLenum typeout,
3502                     void *dataout)
3503 {
3504     int components;
3505     GLushort *beforeImage;
3506     GLushort *afterImage;
3507     PixelStorageModes psm;
3508
3509     if (widthin == 0 || heightin == 0 || widthout == 0 || heightout == 0) {
3510         return 0;
3511     }
3512     if (widthin < 0 || heightin < 0 || widthout < 0 || heightout < 0) {
3513         return GLU_INVALID_VALUE;
3514     }
3515     if (!legalFormat(format) || !legalType(typein) || !legalType(typeout)) {
3516         return GLU_INVALID_ENUM;
3517     }
3518     if (!isLegalFormatForPackedPixelType(format, typein)) {
3519        return GLU_INVALID_OPERATION;
3520     }
3521     if (!isLegalFormatForPackedPixelType(format, typeout)) {
3522        return GLU_INVALID_OPERATION;
3523     }
3524     beforeImage =
3525         malloc(image_size(widthin, heightin, format, GL_UNSIGNED_SHORT));
3526     afterImage =
3527         malloc(image_size(widthout, heightout, format, GL_UNSIGNED_SHORT));
3528     if (beforeImage == NULL || afterImage == NULL) {
3529         free(beforeImage);
3530         free(afterImage);
3531         return GLU_OUT_OF_MEMORY;
3532     }
3533
3534     retrieveStoreModes(&psm);
3535     fill_image(&psm,widthin, heightin, format, typein, is_index(format),
3536             datain, beforeImage);
3537     components = elements_per_group(format, 0);
3538     scale_internal(components, widthin, heightin, beforeImage,
3539             widthout, heightout, afterImage);
3540     empty_image(&psm,widthout, heightout, format, typeout,
3541             is_index(format), afterImage, dataout);
3542     free((GLbyte *) beforeImage);
3543     free((GLbyte *) afterImage);
3544
3545     return 0;
3546 }
3547
3548 int gluBuild1DMipmapLevelsCore(GLenum target, GLint internalFormat,
3549                                GLsizei width,
3550                                GLsizei widthPowerOf2,
3551                                GLenum format, GLenum type,
3552                                GLint userLevel, GLint baseLevel,GLint maxLevel,
3553                                const void *data)
3554 {
3555     GLint newwidth;
3556     GLint level, levels;
3557     GLushort *newImage;
3558     GLint newImage_width;
3559     GLushort *otherImage;
3560     GLushort *imageTemp;
3561     GLint memreq;
3562     GLint cmpts;
3563     PixelStorageModes psm;
3564
3565     assert(checkMipmapArgs(internalFormat,format,type) == 0);
3566     assert(width >= 1);
3567
3568     otherImage = NULL;
3569
3570     newwidth= widthPowerOf2;
3571     levels = computeLog(newwidth);
3572
3573     levels+= userLevel;
3574
3575     retrieveStoreModes(&psm);
3576     newImage = (GLushort *)
3577         malloc(image_size(width, 1, format, GL_UNSIGNED_SHORT));
3578     newImage_width = width;
3579     if (newImage == NULL) {
3580         return GLU_OUT_OF_MEMORY;
3581     }
3582     fill_image(&psm,width, 1, format, type, is_index(format),
3583             data, newImage);
3584     cmpts = elements_per_group(format,type);
3585     glPixelStorei(GL_UNPACK_ALIGNMENT, 2);
3586     glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
3587     glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
3588     glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
3589     /*
3590     ** If swap_bytes was set, swapping occurred in fill_image.
3591     */
3592     glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE);
3593
3594     for (level = userLevel; level <= levels; level++) {
3595         if (newImage_width == newwidth) {
3596             /* Use newImage for this level */
3597             if (baseLevel <= level && level <= maxLevel) {
3598             glTexImage1D(target, level, internalFormat, newImage_width,
3599                     0, format, GL_UNSIGNED_SHORT, (void *) newImage);
3600             }
3601         } else {
3602             if (otherImage == NULL) {
3603                 memreq = image_size(newwidth, 1, format, GL_UNSIGNED_SHORT);
3604                 otherImage = (GLushort *) malloc(memreq);
3605                 if (otherImage == NULL) {
3606                     glPixelStorei(GL_UNPACK_ALIGNMENT, psm.unpack_alignment);
3607                     glPixelStorei(GL_UNPACK_SKIP_ROWS, psm.unpack_skip_rows);
3608                     glPixelStorei(GL_UNPACK_SKIP_PIXELS,psm.unpack_skip_pixels);
3609                     glPixelStorei(GL_UNPACK_ROW_LENGTH, psm.unpack_row_length);
3610                     glPixelStorei(GL_UNPACK_SWAP_BYTES, psm.unpack_swap_bytes);
3611                     free(newImage);
3612                     return GLU_OUT_OF_MEMORY;
3613                 }
3614             }
3615             scale_internal(cmpts, newImage_width, 1, newImage,
3616                     newwidth, 1, otherImage);
3617             /* Swap newImage and otherImage */
3618             imageTemp = otherImage;
3619             otherImage = newImage;
3620             newImage = imageTemp;
3621
3622             newImage_width = newwidth;
3623             if (baseLevel <= level && level <= maxLevel) {
3624             glTexImage1D(target, level, internalFormat, newImage_width,
3625                     0, format, GL_UNSIGNED_SHORT, (void *) newImage);
3626             }
3627         }
3628         if (newwidth > 1) newwidth /= 2;
3629     }
3630     glPixelStorei(GL_UNPACK_ALIGNMENT, psm.unpack_alignment);
3631     glPixelStorei(GL_UNPACK_SKIP_ROWS, psm.unpack_skip_rows);
3632     glPixelStorei(GL_UNPACK_SKIP_PIXELS, psm.unpack_skip_pixels);
3633     glPixelStorei(GL_UNPACK_ROW_LENGTH, psm.unpack_row_length);
3634     glPixelStorei(GL_UNPACK_SWAP_BYTES, psm.unpack_swap_bytes);
3635
3636     free((GLbyte *) newImage);
3637     if (otherImage) {
3638         free((GLbyte *) otherImage);
3639     }
3640     return 0;
3641 }
3642
3643 GLint GLAPIENTRY
3644 gluBuild1DMipmapLevels(GLenum target, GLint internalFormat,
3645                              GLsizei width,
3646                              GLenum format, GLenum type,
3647                              GLint userLevel, GLint baseLevel, GLint maxLevel,
3648                              const void *data)
3649 {
3650    int levels;
3651
3652    int rc= checkMipmapArgs(internalFormat,format,type);
3653    if (rc != 0) return rc;
3654
3655    if (width < 1) {
3656        return GLU_INVALID_VALUE;
3657    }
3658
3659    levels = computeLog(width);
3660
3661    levels+= userLevel;
3662    if (!isLegalLevels(userLevel,baseLevel,maxLevel,levels))
3663       return GLU_INVALID_VALUE;
3664
3665    return gluBuild1DMipmapLevelsCore(target, internalFormat,
3666                                      width,
3667                                      width,format, type,
3668                                      userLevel, baseLevel, maxLevel,
3669                                      data);
3670 } /* gluBuild1DMipmapLevels() */
3671
3672 GLint GLAPIENTRY
3673 gluBuild1DMipmaps(GLenum target, GLint internalFormat, GLsizei width,
3674                         GLenum format, GLenum type,
3675                         const void *data)
3676 {
3677    GLint widthPowerOf2;
3678    int levels;
3679    GLint dummy;
3680
3681    int rc= checkMipmapArgs(internalFormat,format,type);
3682    if (rc != 0) return rc;
3683
3684    if (width < 1) {
3685        return GLU_INVALID_VALUE;
3686    }
3687
3688    closestFit(target,width,1,internalFormat,format,type,&widthPowerOf2,&dummy);
3689    levels = computeLog(widthPowerOf2);
3690
3691    return gluBuild1DMipmapLevelsCore(target,internalFormat,
3692                                      width,
3693                                      widthPowerOf2,
3694                                      format,type,0,0,levels,data);
3695 }
3696
3697 static int bitmapBuild2DMipmaps(GLenum target, GLint internalFormat,
3698                      GLint width, GLint height, GLenum format,
3699                      GLenum type, const void *data)
3700 {
3701     GLint newwidth, newheight;
3702     GLint level, levels;
3703     GLushort *newImage;
3704     GLint newImage_width;
3705     GLint newImage_height;
3706     GLushort *otherImage;
3707     GLushort *imageTemp;
3708     GLint memreq;
3709     GLint cmpts;
3710     PixelStorageModes psm;
3711
3712     retrieveStoreModes(&psm);
3713
3714 #if 0
3715     glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxsize);
3716     newwidth = nearestPower(width);
3717     if (newwidth > maxsize) newwidth = maxsize;
3718     newheight = nearestPower(height);
3719     if (newheight > maxsize) newheight = maxsize;
3720 #else
3721     closestFit(target,width,height,internalFormat,format,type,
3722                &newwidth,&newheight);
3723 #endif
3724     levels = computeLog(newwidth);
3725     level = computeLog(newheight);
3726     if (level > levels) levels=level;
3727
3728     otherImage = NULL;
3729     newImage = (GLushort *)
3730         malloc(image_size(width, height, format, GL_UNSIGNED_SHORT));
3731     newImage_width = width;
3732     newImage_height = height;
3733     if (newImage == NULL) {
3734         return GLU_OUT_OF_MEMORY;
3735     }
3736
3737     fill_image(&psm,width, height, format, type, is_index(format),
3738           data, newImage);
3739
3740     cmpts = elements_per_group(format,type);
3741     glPixelStorei(GL_UNPACK_ALIGNMENT, 2);
3742     glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
3743     glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
3744     glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
3745     /*
3746     ** If swap_bytes was set, swapping occurred in fill_image.
3747     */
3748     glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE);
3749
3750     for (level = 0; level <= levels; level++) {
3751         if (newImage_width == newwidth && newImage_height == newheight) {            /* Use newImage for this level */
3752             glTexImage2D(target, level, internalFormat, newImage_width,
3753                     newImage_height, 0, format, GL_UNSIGNED_SHORT,
3754                     (void *) newImage);
3755         } else {
3756             if (otherImage == NULL) {
3757                 memreq =
3758                     image_size(newwidth, newheight, format, GL_UNSIGNED_SHORT);
3759                 otherImage = (GLushort *) malloc(memreq);
3760                 if (otherImage == NULL) {
3761                     glPixelStorei(GL_UNPACK_ALIGNMENT, psm.unpack_alignment);
3762                     glPixelStorei(GL_UNPACK_SKIP_ROWS, psm.unpack_skip_rows);
3763                     glPixelStorei(GL_UNPACK_SKIP_PIXELS,psm.unpack_skip_pixels);
3764                     glPixelStorei(GL_UNPACK_ROW_LENGTH, psm.unpack_row_length);
3765                     glPixelStorei(GL_UNPACK_SWAP_BYTES, psm.unpack_swap_bytes);
3766                     free(newImage);
3767                     return GLU_OUT_OF_MEMORY;
3768                 }
3769             }
3770             scale_internal(cmpts, newImage_width, newImage_height, newImage,
3771                     newwidth, newheight, otherImage);
3772             /* Swap newImage and otherImage */
3773             imageTemp = otherImage;
3774             otherImage = newImage;
3775             newImage = imageTemp;
3776
3777             newImage_width = newwidth;
3778             newImage_height = newheight;
3779             glTexImage2D(target, level, internalFormat, newImage_width,
3780                     newImage_height, 0, format, GL_UNSIGNED_SHORT,
3781                     (void *) newImage);
3782         }
3783         if (newwidth > 1) newwidth /= 2;
3784         if (newheight > 1) newheight /= 2;
3785     }
3786     glPixelStorei(GL_UNPACK_ALIGNMENT, psm.unpack_alignment);
3787     glPixelStorei(GL_UNPACK_SKIP_ROWS, psm.unpack_skip_rows);
3788     glPixelStorei(GL_UNPACK_SKIP_PIXELS, psm.unpack_skip_pixels);
3789     glPixelStorei(GL_UNPACK_ROW_LENGTH, psm.unpack_row_length);
3790     glPixelStorei(GL_UNPACK_SWAP_BYTES, psm.unpack_swap_bytes);
3791
3792     free((GLbyte *) newImage);
3793     if (otherImage) {
3794         free((GLbyte *) otherImage);
3795     }
3796     return 0;
3797 }
3798
3799 /* To make swapping images less error prone */
3800 #define __GLU_INIT_SWAP_IMAGE void *tmpImage
3801 #define __GLU_SWAP_IMAGE(a,b) tmpImage = a; a = b; b = tmpImage;
3802
3803 static int gluBuild2DMipmapLevelsCore(GLenum target, GLint internalFormat,
3804                                       GLsizei width, GLsizei height,
3805                                       GLsizei widthPowerOf2,
3806                                       GLsizei heightPowerOf2,
3807                                       GLenum format, GLenum type,
3808                                       GLint userLevel,
3809                                       GLint baseLevel,GLint maxLevel,
3810                                       const void *data)
3811 {
3812     GLint newwidth, newheight;
3813     GLint level, levels;
3814     const void *usersImage; /* passed from user. Don't touch! */
3815     void *srcImage, *dstImage; /* scratch area to build mipmapped images */
3816     __GLU_INIT_SWAP_IMAGE;
3817     GLint memreq;
3818     GLint cmpts;
3819
3820     GLint myswap_bytes, groups_per_line, element_size, group_size;
3821     GLint rowsize, padding;
3822     PixelStorageModes psm;
3823
3824     assert(checkMipmapArgs(internalFormat,format,type) == 0);
3825     assert(width >= 1 && height >= 1);
3826
3827     if(type == GL_BITMAP) {
3828         return bitmapBuild2DMipmaps(target, internalFormat, width, height,
3829                 format, type, data);
3830     }
3831
3832     srcImage = dstImage = NULL;
3833
3834     newwidth= widthPowerOf2;
3835     newheight= heightPowerOf2;
3836     levels = computeLog(newwidth);
3837     level = computeLog(newheight);
3838     if (level > levels) levels=level;
3839
3840     levels+= userLevel;
3841
3842     retrieveStoreModes(&psm);
3843     myswap_bytes = psm.unpack_swap_bytes;
3844     cmpts = elements_per_group(format,type);
3845     if (psm.unpack_row_length > 0) {
3846         groups_per_line = psm.unpack_row_length;
3847     } else {
3848         groups_per_line = width;
3849     }
3850
3851     element_size = bytes_per_element(type);
3852     group_size = element_size * cmpts;
3853     if (element_size == 1) myswap_bytes = 0;
3854
3855     rowsize = groups_per_line * group_size;
3856     padding = (rowsize % psm.unpack_alignment);
3857     if (padding) {
3858         rowsize += psm.unpack_alignment - padding;
3859     }
3860     usersImage = (const GLubyte *) data + psm.unpack_skip_rows * rowsize +
3861         psm.unpack_skip_pixels * group_size;
3862
3863     glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
3864     glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
3865     glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
3866
3867     level = userLevel;
3868
3869     /* already power-of-two square */
3870     if (width == newwidth && height == newheight) {
3871         /* Use usersImage for level userLevel */
3872         if (baseLevel <= level && level <= maxLevel) {
3873         glPixelStorei(GL_UNPACK_ROW_LENGTH, psm.unpack_row_length);
3874         glTexImage2D(target, level, internalFormat, width,
3875                 height, 0, format, type,
3876                 usersImage);
3877         }
3878         glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
3879         if(levels == 0) { /* we're done. clean up and return */
3880           glPixelStorei(GL_UNPACK_ALIGNMENT, psm.unpack_alignment);
3881           glPixelStorei(GL_UNPACK_SKIP_ROWS, psm.unpack_skip_rows);
3882           glPixelStorei(GL_UNPACK_SKIP_PIXELS, psm.unpack_skip_pixels);
3883           glPixelStorei(GL_UNPACK_ROW_LENGTH, psm.unpack_row_length);
3884           glPixelStorei(GL_UNPACK_SWAP_BYTES, psm.unpack_swap_bytes);
3885           return 0;
3886         }
3887         {
3888            int nextWidth= newwidth/2;
3889            int nextHeight= newheight/2;
3890
3891            /* clamp to 1 */
3892            if (nextWidth < 1) nextWidth= 1;
3893            if (nextHeight < 1) nextHeight= 1;
3894         memreq = image_size(nextWidth, nextHeight, format, type);
3895         }
3896
3897         switch(type) {
3898         case GL_UNSIGNED_BYTE:
3899           dstImage = (GLubyte *)malloc(memreq);
3900           break;
3901         case GL_BYTE:
3902           dstImage = (GLbyte *)malloc(memreq);
3903           break;
3904         case GL_UNSIGNED_SHORT:
3905           dstImage = (GLushort *)malloc(memreq);
3906           break;
3907         case GL_SHORT:
3908           dstImage = (GLshort *)malloc(memreq);
3909           break;
3910         case GL_UNSIGNED_INT:
3911           dstImage = (GLuint *)malloc(memreq);
3912           break;
3913         case GL_INT:
3914           dstImage = (GLint *)malloc(memreq);
3915           break;
3916         case GL_FLOAT:
3917           dstImage = (GLfloat *)malloc(memreq);
3918           break;
3919         case GL_UNSIGNED_BYTE_3_3_2:
3920         case GL_UNSIGNED_BYTE_2_3_3_REV:
3921           dstImage = (GLubyte *)malloc(memreq);
3922           break;
3923         case GL_UNSIGNED_SHORT_5_6_5:
3924         case GL_UNSIGNED_SHORT_5_6_5_REV:
3925         case GL_UNSIGNED_SHORT_4_4_4_4:
3926         case GL_UNSIGNED_SHORT_4_4_4_4_REV:
3927         case GL_UNSIGNED_SHORT_5_5_5_1:
3928         case GL_UNSIGNED_SHORT_1_5_5_5_REV:
3929           dstImage = (GLushort *)malloc(memreq);
3930           break;
3931         case GL_UNSIGNED_INT_8_8_8_8:
3932         case GL_UNSIGNED_INT_8_8_8_8_REV:
3933         case GL_UNSIGNED_INT_10_10_10_2:
3934         case GL_UNSIGNED_INT_2_10_10_10_REV:
3935           dstImage = (GLuint *)malloc(memreq);  
3936           break;
3937         default:
3938           return GLU_INVALID_ENUM;
3939         }
3940         if (dstImage == NULL) {
3941           glPixelStorei(GL_UNPACK_ALIGNMENT, psm.unpack_alignment);
3942           glPixelStorei(GL_UNPACK_SKIP_ROWS, psm.unpack_skip_rows);
3943           glPixelStorei(GL_UNPACK_SKIP_PIXELS, psm.unpack_skip_pixels);
3944           glPixelStorei(GL_UNPACK_ROW_LENGTH, psm.unpack_row_length);
3945           glPixelStorei(GL_UNPACK_SWAP_BYTES, psm.unpack_swap_bytes);
3946           return GLU_OUT_OF_MEMORY;
3947         }
3948         else
3949           switch(type) {
3950           case GL_UNSIGNED_BYTE:
3951             halveImage_ubyte(cmpts, width, height,
3952                              (const GLubyte *)usersImage, (GLubyte *)dstImage,
3953                              element_size, rowsize, group_size);
3954             break;
3955           case GL_BYTE:
3956             halveImage_byte(cmpts, width, height,
3957                             (const GLbyte *)usersImage, (GLbyte *)dstImage,
3958                             element_size, rowsize, group_size);
3959             break;
3960           case GL_UNSIGNED_SHORT:
3961             halveImage_ushort(cmpts, width, height,
3962                               (const GLushort *)usersImage, (GLushort *)dstImage,
3963                               element_size, rowsize, group_size, myswap_bytes);
3964             break;
3965           case GL_SHORT:
3966             halveImage_short(cmpts, width, height,
3967                              (const GLshort *)usersImage, (GLshort *)dstImage,
3968                              element_size, rowsize, group_size, myswap_bytes);
3969             break;
3970           case GL_UNSIGNED_INT:
3971             halveImage_uint(cmpts, width, height,
3972                             (const GLuint *)usersImage, (GLuint *)dstImage,
3973                             element_size, rowsize, group_size, myswap_bytes);
3974             break;
3975           case GL_INT:
3976             halveImage_int(cmpts, width, height,
3977                            (const GLint *)usersImage, (GLint *)dstImage,
3978                            element_size, rowsize, group_size, myswap_bytes);
3979             break;
3980           case GL_FLOAT:
3981             halveImage_float(cmpts, width, height,
3982                              (const GLfloat *)usersImage, (GLfloat *)dstImage,
3983                              element_size, rowsize, group_size, myswap_bytes);
3984             break;
3985           case GL_UNSIGNED_BYTE_3_3_2:
3986             assert(format == GL_RGB);
3987             halveImagePackedPixel(3,extract332,shove332,
3988                                   width,height,usersImage,dstImage,
3989                                   element_size,rowsize,myswap_bytes);
3990             break;
3991           case GL_UNSIGNED_BYTE_2_3_3_REV:
3992             assert(format == GL_RGB);
3993             halveImagePackedPixel(3,extract233rev,shove233rev,
3994                                   width,height,usersImage,dstImage,
3995                                   element_size,rowsize,myswap_bytes);
3996             break;
3997           case GL_UNSIGNED_SHORT_5_6_5:
3998             halveImagePackedPixel(3,extract565,shove565,
3999                                   width,height,usersImage,dstImage,
4000                                   element_size,rowsize,myswap_bytes);
4001             break;
4002           case GL_UNSIGNED_SHORT_5_6_5_REV:
4003             halveImagePackedPixel(3,extract565rev,shove565rev,
4004                                   width,height,usersImage,dstImage,
4005                                   element_size,rowsize,myswap_bytes);
4006             break;
4007           case GL_UNSIGNED_SHORT_4_4_4_4:
4008             halveImagePackedPixel(4,extract4444,shove4444,
4009                                   width,height,usersImage,dstImage,
4010                                   element_size,rowsize,myswap_bytes);
4011             break;
4012           case GL_UNSIGNED_SHORT_4_4_4_4_REV:
4013             halveImagePackedPixel(4,extract4444rev,shove4444rev,
4014                                   width,height,usersImage,dstImage,
4015                                   element_size,rowsize,myswap_bytes);
4016             break;
4017           case GL_UNSIGNED_SHORT_5_5_5_1:
4018             halveImagePackedPixel(4,extract5551,shove5551,
4019                                   width,height,usersImage,dstImage,
4020                                   element_size,rowsize,myswap_bytes);
4021             break;
4022           case GL_UNSIGNED_SHORT_1_5_5_5_REV:
4023             halveImagePackedPixel(4,extract1555rev,shove1555rev,
4024                                   width,height,usersImage,dstImage,
4025                                   element_size,rowsize,myswap_bytes);
4026             break;
4027           case GL_UNSIGNED_INT_8_8_8_8:
4028             halveImagePackedPixel(4,extract8888,shove8888,
4029                                   width,height,usersImage,dstImage,
4030                                   element_size,rowsize,myswap_bytes);
4031             break;
4032           case GL_UNSIGNED_INT_8_8_8_8_REV:
4033             halveImagePackedPixel(4,extract8888rev,shove8888rev,
4034                                   width,height,usersImage,dstImage,
4035                                   element_size,rowsize,myswap_bytes);
4036             break;
4037           case GL_UNSIGNED_INT_10_10_10_2:
4038             halveImagePackedPixel(4,extract1010102,shove1010102,
4039                                   width,height,usersImage,dstImage,
4040                                   element_size,rowsize,myswap_bytes);
4041             break;
4042           case GL_UNSIGNED_INT_2_10_10_10_REV:
4043             halveImagePackedPixel(4,extract2101010rev,shove2101010rev,
4044                                   width,height,usersImage,dstImage,
4045                                   element_size,rowsize,myswap_bytes);
4046             break;
4047           default:
4048             assert(0);
4049             break;
4050           }
4051         newwidth = width/2;
4052         newheight = height/2;
4053         /* clamp to 1 */
4054         if (newwidth < 1) newwidth= 1;
4055         if (newheight < 1) newheight= 1;
4056
4057         myswap_bytes = 0;
4058         rowsize = newwidth * group_size;
4059         memreq = image_size(newwidth, newheight, format, type);
4060         /* Swap srcImage and dstImage */
4061         __GLU_SWAP_IMAGE(srcImage,dstImage);
4062         switch(type) {
4063         case GL_UNSIGNED_BYTE:
4064           dstImage = (GLubyte *)malloc(memreq);
4065           break;
4066         case GL_BYTE:
4067           dstImage = (GLbyte *)malloc(memreq);
4068           break;
4069         case GL_UNSIGNED_SHORT:
4070           dstImage = (GLushort *)malloc(memreq);
4071           break;
4072         case GL_SHORT:
4073           dstImage = (GLshort *)malloc(memreq);
4074           break;
4075         case GL_UNSIGNED_INT:
4076           dstImage = (GLuint *)malloc(memreq);
4077           break;
4078         case GL_INT:
4079           dstImage = (GLint *)malloc(memreq);
4080           break;
4081         case GL_FLOAT:
4082           dstImage = (GLfloat *)malloc(memreq);
4083           break;
4084         case GL_UNSIGNED_BYTE_3_3_2:
4085         case GL_UNSIGNED_BYTE_2_3_3_REV:
4086           dstImage = (GLubyte *)malloc(memreq);
4087           break;
4088         case GL_UNSIGNED_SHORT_5_6_5:
4089         case GL_UNSIGNED_SHORT_5_6_5_REV:
4090         case GL_UNSIGNED_SHORT_4_4_4_4:
4091         case GL_UNSIGNED_SHORT_4_4_4_4_REV:
4092         case GL_UNSIGNED_SHORT_5_5_5_1:
4093         case GL_UNSIGNED_SHORT_1_5_5_5_REV:
4094           dstImage = (GLushort *)malloc(memreq);
4095           break;
4096         case GL_UNSIGNED_INT_8_8_8_8:
4097         case GL_UNSIGNED_INT_8_8_8_8_REV:
4098         case GL_UNSIGNED_INT_10_10_10_2:
4099         case GL_UNSIGNED_INT_2_10_10_10_REV:
4100           dstImage = (GLuint *)malloc(memreq);
4101           break;
4102         default:
4103           return GLU_INVALID_ENUM;
4104         }
4105         if (dstImage == NULL) {
4106           glPixelStorei(GL_UNPACK_ALIGNMENT, psm.unpack_alignment);
4107           glPixelStorei(GL_UNPACK_SKIP_ROWS, psm.unpack_skip_rows);
4108           glPixelStorei(GL_UNPACK_SKIP_PIXELS, psm.unpack_skip_pixels);
4109           glPixelStorei(GL_UNPACK_ROW_LENGTH, psm.unpack_row_length);
4110           glPixelStorei(GL_UNPACK_SWAP_BYTES, psm.unpack_swap_bytes);
4111           return GLU_OUT_OF_MEMORY;
4112         }
4113         /* level userLevel+1 is in srcImage; level userLevel already saved */
4114         level = userLevel+1;
4115     } else { /* user's image is *not* nice power-of-2 sized square */
4116         memreq = image_size(newwidth, newheight, format, type);
4117         switch(type) {
4118             case GL_UNSIGNED_BYTE:
4119                 dstImage = (GLubyte *)malloc(memreq);
4120                 break;
4121             case GL_BYTE:
4122                 dstImage = (GLbyte *)malloc(memreq);
4123                 break;
4124             case GL_UNSIGNED_SHORT:
4125                 dstImage = (GLushort *)malloc(memreq);
4126                 break;
4127             case GL_SHORT:
4128                 dstImage = (GLshort *)malloc(memreq);
4129                 break;
4130             case GL_UNSIGNED_INT:
4131                 dstImage = (GLuint *)malloc(memreq);
4132                 break;
4133             case GL_INT:
4134                 dstImage = (GLint *)malloc(memreq);
4135                 break;
4136             case GL_FLOAT:
4137                 dstImage = (GLfloat *)malloc(memreq);
4138                 break;
4139             case GL_UNSIGNED_BYTE_3_3_2:
4140             case GL_UNSIGNED_BYTE_2_3_3_REV:
4141                 dstImage = (GLubyte *)malloc(memreq);
4142                 break;
4143             case GL_UNSIGNED_SHORT_5_6_5:
4144             case GL_UNSIGNED_SHORT_5_6_5_REV:
4145             case GL_UNSIGNED_SHORT_4_4_4_4:
4146             case GL_UNSIGNED_SHORT_4_4_4_4_REV:
4147             case GL_UNSIGNED_SHORT_5_5_5_1:
4148             case GL_UNSIGNED_SHORT_1_5_5_5_REV:
4149                 dstImage = (GLushort *)malloc(memreq);
4150                 break;
4151             case GL_UNSIGNED_INT_8_8_8_8:
4152             case GL_UNSIGNED_INT_8_8_8_8_REV:
4153             case GL_UNSIGNED_INT_10_10_10_2:
4154             case GL_UNSIGNED_INT_2_10_10_10_REV:
4155                 dstImage = (GLuint *)malloc(memreq);
4156                 break;
4157             default:
4158                 return GLU_INVALID_ENUM;
4159         }
4160
4161         if (dstImage == NULL) {
4162             glPixelStorei(GL_UNPACK_ALIGNMENT, psm.unpack_alignment);
4163             glPixelStorei(GL_UNPACK_SKIP_ROWS, psm.unpack_skip_rows);
4164             glPixelStorei(GL_UNPACK_SKIP_PIXELS, psm.unpack_skip_pixels);
4165             glPixelStorei(GL_UNPACK_ROW_LENGTH, psm.unpack_row_length);
4166             glPixelStorei(GL_UNPACK_SWAP_BYTES, psm.unpack_swap_bytes);
4167             return GLU_OUT_OF_MEMORY;
4168         }
4169
4170         switch(type) {
4171         case GL_UNSIGNED_BYTE:
4172             scale_internal_ubyte(cmpts, width, height,
4173                                  (const GLubyte *)usersImage, newwidth, newheight,
4174                                  (GLubyte *)dstImage, element_size,
4175                                  rowsize, group_size);
4176             break;
4177         case GL_BYTE:
4178             scale_internal_byte(cmpts, width, height,
4179                                 (const GLbyte *)usersImage, newwidth, newheight,
4180                                 (GLbyte *)dstImage, element_size,
4181                                 rowsize, group_size);
4182             break;
4183         case GL_UNSIGNED_SHORT:
4184             scale_internal_ushort(cmpts, width, height,
4185                                   (const GLushort *)usersImage, newwidth, newheight,
4186                                   (GLushort *)dstImage, element_size,
4187                                   rowsize, group_size, myswap_bytes);
4188             break;
4189         case GL_SHORT:
4190             scale_internal_short(cmpts, width, height,
4191                                  (const GLshort *)usersImage, newwidth, newheight,
4192                                  (GLshort *)dstImage, element_size,
4193                                  rowsize, group_size, myswap_bytes);
4194             break;
4195         case GL_UNSIGNED_INT:
4196             scale_internal_uint(cmpts, width, height,
4197                                 (const GLuint *)usersImage, newwidth, newheight,
4198                                 (GLuint *)dstImage, element_size,
4199                                 rowsize, group_size, myswap_bytes);
4200             break;
4201         case GL_INT:
4202             scale_internal_int(cmpts, width, height,
4203                                (const GLint *)usersImage, newwidth, newheight,
4204                                (GLint *)dstImage, element_size,
4205                                rowsize, group_size, myswap_bytes);
4206             break;
4207         case GL_FLOAT:
4208             scale_internal_float(cmpts, width, height,
4209                                  (const GLfloat *)usersImage, newwidth, newheight,
4210                                  (GLfloat *)dstImage, element_size,
4211                                  rowsize, group_size, myswap_bytes);
4212             break;
4213         case GL_UNSIGNED_BYTE_3_3_2:
4214             scaleInternalPackedPixel(3,extract332,shove332,
4215                                      width, height,usersImage,
4216                                      newwidth,newheight,(void *)dstImage,
4217                                      element_size,rowsize,myswap_bytes);
4218             break;
4219         case GL_UNSIGNED_BYTE_2_3_3_REV:
4220             scaleInternalPackedPixel(3,extract233rev,shove233rev,
4221                                      width, height,usersImage,
4222                                      newwidth,newheight,(void *)dstImage,
4223                                      element_size,rowsize,myswap_bytes);
4224             break;
4225         case GL_UNSIGNED_SHORT_5_6_5:
4226             scaleInternalPackedPixel(3,extract565,shove565,
4227                                      width, height,usersImage,
4228                                      newwidth,newheight,(void *)dstImage,
4229                                      element_size,rowsize,myswap_bytes);
4230             break;
4231         case GL_UNSIGNED_SHORT_5_6_5_REV:
4232             scaleInternalPackedPixel(3,extract565rev,shove565rev,
4233                                      width, height,usersImage,
4234                                      newwidth,newheight,(void *)dstImage,
4235                                      element_size,rowsize,myswap_bytes);
4236             break;
4237         case GL_UNSIGNED_SHORT_4_4_4_4:
4238             scaleInternalPackedPixel(4,extract4444,shove4444,
4239                                      width, height,usersImage,
4240                                      newwidth,newheight,(void *)dstImage,
4241                                      element_size,rowsize,myswap_bytes);
4242             break;
4243         case GL_UNSIGNED_SHORT_4_4_4_4_REV:
4244             scaleInternalPackedPixel(4,extract4444rev,shove4444rev,
4245                                      width, height,usersImage,
4246                                      newwidth,newheight,(void *)dstImage,
4247                                      element_size,rowsize,myswap_bytes);
4248             break;
4249         case GL_UNSIGNED_SHORT_5_5_5_1:
4250             scaleInternalPackedPixel(4,extract5551,shove5551,
4251                                      width, height,usersImage,
4252                                      newwidth,newheight,(void *)dstImage,
4253                                      element_size,rowsize,myswap_bytes);
4254             break;
4255         case GL_UNSIGNED_SHORT_1_5_5_5_REV:
4256             scaleInternalPackedPixel(4,extract1555rev,shove1555rev,
4257                                      width, height,usersImage,
4258                                      newwidth,newheight,(void *)dstImage,
4259                                      element_size,rowsize,myswap_bytes);
4260             break;
4261         case GL_UNSIGNED_INT_8_8_8_8:
4262             scaleInternalPackedPixel(4,extract8888,shove8888,
4263                                      width, height,usersImage,
4264                                      newwidth,newheight,(void *)dstImage,
4265                                      element_size,rowsize,myswap_bytes);
4266             break;
4267         case GL_UNSIGNED_INT_8_8_8_8_REV:
4268             scaleInternalPackedPixel(4,extract8888rev,shove8888rev,
4269                                      width, height,usersImage,
4270                                      newwidth,newheight,(void *)dstImage,
4271                                      element_size,rowsize,myswap_bytes);
4272             break;
4273         case GL_UNSIGNED_INT_10_10_10_2:
4274             scaleInternalPackedPixel(4,extract1010102,shove1010102,
4275                                      width, height,usersImage,
4276                                      newwidth,newheight,(void *)dstImage,
4277                                      element_size,rowsize,myswap_bytes);
4278             break;
4279         case GL_UNSIGNED_INT_2_10_10_10_REV:
4280             scaleInternalPackedPixel(4,extract2101010rev,shove2101010rev,
4281                                      width, height,usersImage,
4282                                      newwidth,newheight,(void *)dstImage,
4283                                      element_size,rowsize,myswap_bytes);
4284             break;
4285         default:
4286             assert(0);
4287             break;
4288         }
4289         myswap_bytes = 0;
4290         rowsize = newwidth * group_size;
4291         /* Swap dstImage and srcImage */
4292         __GLU_SWAP_IMAGE(srcImage,dstImage);
4293
4294         if(levels != 0) { /* use as little memory as possible */
4295           {
4296              int nextWidth= newwidth/2;
4297              int nextHeight= newheight/2;
4298              if (nextWidth < 1) nextWidth= 1;
4299              if (nextHeight < 1) nextHeight= 1; 
4300
4301           memreq = image_size(nextWidth, nextHeight, format, type);
4302           }
4303
4304           switch(type) {
4305           case GL_UNSIGNED_BYTE:
4306             dstImage = (GLubyte *)malloc(memreq);
4307             break;
4308           case GL_BYTE:
4309             dstImage = (GLbyte *)malloc(memreq);
4310             break;
4311           case GL_UNSIGNED_SHORT:
4312             dstImage = (GLushort *)malloc(memreq);
4313             break;
4314           case GL_SHORT:
4315             dstImage = (GLshort *)malloc(memreq);
4316             break;
4317           case GL_UNSIGNED_INT:
4318             dstImage = (GLuint *)malloc(memreq);
4319             break;
4320           case GL_INT:
4321             dstImage = (GLint *)malloc(memreq);
4322             break;
4323           case GL_FLOAT:
4324             dstImage = (GLfloat *)malloc(memreq);
4325             break;
4326           case GL_UNSIGNED_BYTE_3_3_2:
4327           case GL_UNSIGNED_BYTE_2_3_3_REV:
4328             dstImage = (GLubyte *)malloc(memreq);
4329             break;
4330           case GL_UNSIGNED_SHORT_5_6_5:
4331           case GL_UNSIGNED_SHORT_5_6_5_REV:
4332           case GL_UNSIGNED_SHORT_4_4_4_4:
4333           case GL_UNSIGNED_SHORT_4_4_4_4_REV:
4334           case GL_UNSIGNED_SHORT_5_5_5_1:
4335           case GL_UNSIGNED_SHORT_1_5_5_5_REV:
4336             dstImage = (GLushort *)malloc(memreq);
4337             break;
4338           case GL_UNSIGNED_INT_8_8_8_8:
4339           case GL_UNSIGNED_INT_8_8_8_8_REV:
4340           case GL_UNSIGNED_INT_10_10_10_2:
4341           case GL_UNSIGNED_INT_2_10_10_10_REV:
4342             dstImage = (GLuint *)malloc(memreq);
4343             break;
4344           default:
4345             return GLU_INVALID_ENUM;
4346           }
4347           if (dstImage == NULL) {
4348             glPixelStorei(GL_UNPACK_ALIGNMENT, psm.unpack_alignment);
4349             glPixelStorei(GL_UNPACK_SKIP_ROWS, psm.unpack_skip_rows);
4350             glPixelStorei(GL_UNPACK_SKIP_PIXELS, psm.unpack_skip_pixels);
4351             glPixelStorei(GL_UNPACK_ROW_LENGTH, psm.unpack_row_length);
4352             glPixelStorei(GL_UNPACK_SWAP_BYTES, psm.unpack_swap_bytes);
4353             free(srcImage);
4354             return GLU_OUT_OF_MEMORY;
4355           }
4356         }
4357         /* level userLevel is in srcImage; nothing saved yet */
4358         level = userLevel;
4359     }
4360
4361     glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE);
4362     if (baseLevel <= level && level <= maxLevel) {
4363     glTexImage2D(target, level, internalFormat, newwidth, newheight, 0,
4364                  format, type, (void *)srcImage);
4365     }
4366
4367     level++; /* update current level for the loop */
4368     for (; level <= levels; level++) {
4369         switch(type) {
4370             case GL_UNSIGNED_BYTE:
4371                 halveImage_ubyte(cmpts, newwidth, newheight,
4372                 (GLubyte *)srcImage, (GLubyte *)dstImage, element_size,
4373                 rowsize, group_size);
4374                 break;
4375             case GL_BYTE:
4376                 halveImage_byte(cmpts, newwidth, newheight,
4377                 (GLbyte *)srcImage, (GLbyte *)dstImage, element_size,
4378                 rowsize, group_size);
4379                 break;
4380             case GL_UNSIGNED_SHORT:
4381                 halveImage_ushort(cmpts, newwidth, newheight,
4382                 (GLushort *)srcImage, (GLushort *)dstImage, element_size,
4383                 rowsize, group_size, myswap_bytes);
4384                 break;
4385             case GL_SHORT:
4386                 halveImage_short(cmpts, newwidth, newheight,
4387                 (GLshort *)srcImage, (GLshort *)dstImage, element_size,
4388                 rowsize, group_size, myswap_bytes);
4389                 break;
4390             case GL_UNSIGNED_INT:
4391                 halveImage_uint(cmpts, newwidth, newheight,
4392                 (GLuint *)srcImage, (GLuint *)dstImage, element_size,
4393                 rowsize, group_size, myswap_bytes);
4394                 break;
4395             case GL_INT:
4396                 halveImage_int(cmpts, newwidth, newheight,
4397                 (GLint *)srcImage, (GLint *)dstImage, element_size,
4398                 rowsize, group_size, myswap_bytes);
4399                 break;
4400             case GL_FLOAT:
4401                 halveImage_float(cmpts, newwidth, newheight,
4402                 (GLfloat *)srcImage, (GLfloat *)dstImage, element_size,
4403                 rowsize, group_size, myswap_bytes);
4404                 break;
4405             case GL_UNSIGNED_BYTE_3_3_2:
4406                 halveImagePackedPixel(3,extract332,shove332,
4407                                       newwidth,newheight,
4408                                       srcImage,dstImage,element_size,rowsize,
4409                                       myswap_bytes);
4410                 break;
4411             case GL_UNSIGNED_BYTE_2_3_3_REV:
4412                 halveImagePackedPixel(3,extract233rev,shove233rev,
4413                                       newwidth,newheight,
4414                                       srcImage,dstImage,element_size,rowsize,
4415                                       myswap_bytes);
4416                 break;
4417             case GL_UNSIGNED_SHORT_5_6_5:
4418                 halveImagePackedPixel(3,extract565,shove565,
4419                                       newwidth,newheight,
4420                                       srcImage,dstImage,element_size,rowsize,
4421                                       myswap_bytes);
4422                 break;
4423             case GL_UNSIGNED_SHORT_5_6_5_REV:
4424                 halveImagePackedPixel(3,extract565rev,shove565rev,
4425                                       newwidth,newheight,
4426                                       srcImage,dstImage,element_size,rowsize,
4427                                       myswap_bytes);
4428                 break;
4429             case GL_UNSIGNED_SHORT_4_4_4_4:
4430                 halveImagePackedPixel(4,extract4444,shove4444,
4431                                       newwidth,newheight,
4432                                       srcImage,dstImage,element_size,rowsize,
4433                                       myswap_bytes);
4434                 break;
4435             case GL_UNSIGNED_SHORT_4_4_4_4_REV:
4436                 halveImagePackedPixel(4,extract4444rev,shove4444rev,
4437                                       newwidth,newheight,
4438                                       srcImage,dstImage,element_size,rowsize,
4439                                       myswap_bytes);
4440                 break;
4441             case GL_UNSIGNED_SHORT_5_5_5_1:             
4442                 halveImagePackedPixel(4,extract5551,shove5551,
4443                                       newwidth,newheight,
4444                                       srcImage,dstImage,element_size,rowsize,
4445                                       myswap_bytes);
4446                 break;
4447             case GL_UNSIGNED_SHORT_1_5_5_5_REV:                 
4448                 halveImagePackedPixel(4,extract1555rev,shove1555rev,
4449                                       newwidth,newheight,
4450                                       srcImage,dstImage,element_size,rowsize,
4451                                       myswap_bytes);
4452                 break;
4453             case GL_UNSIGNED_INT_8_8_8_8:
4454                 halveImagePackedPixel(4,extract8888,shove8888,
4455                                       newwidth,newheight,
4456                                       srcImage,dstImage,element_size,rowsize,
4457                                       myswap_bytes);
4458                 break;
4459             case GL_UNSIGNED_INT_8_8_8_8_REV:
4460                 halveImagePackedPixel(4,extract8888rev,shove8888rev,
4461                                       newwidth,newheight,
4462                                       srcImage,dstImage,element_size,rowsize,
4463                                       myswap_bytes);
4464                 break;
4465             case GL_UNSIGNED_INT_10_10_10_2:
4466                 halveImagePackedPixel(4,extract1010102,shove1010102,
4467                                       newwidth,newheight,
4468                                       srcImage,dstImage,element_size,rowsize,
4469                                       myswap_bytes);
4470                 break;
4471             case GL_UNSIGNED_INT_2_10_10_10_REV:
4472                 halveImagePackedPixel(4,extract2101010rev,shove2101010rev,
4473                                       newwidth,newheight,
4474                                       srcImage,dstImage,element_size,rowsize,
4475                                       myswap_bytes);
4476                 break;
4477             default:
4478                 assert(0);
4479                 break;
4480         }
4481
4482         __GLU_SWAP_IMAGE(srcImage,dstImage);
4483
4484         if (newwidth > 1) { newwidth /= 2; rowsize /= 2;}
4485         if (newheight > 1) newheight /= 2;
4486       {
4487        /* compute amount to pad per row, if any */
4488        int rowPad= rowsize % psm.unpack_alignment;
4489
4490        /* should row be padded? */
4491        if (rowPad == 0) {       /* nope, row should not be padded */
4492            /* call tex image with srcImage untouched since it's not padded */
4493            if (baseLevel <= level && level <= maxLevel) {
4494            glTexImage2D(target, level, internalFormat, newwidth, newheight, 0,
4495            format, type, (void *) srcImage);
4496            }
4497        }
4498        else {                   /* yes, row should be padded */
4499           /* compute length of new row in bytes, including padding */
4500           int newRowLength= rowsize + psm.unpack_alignment - rowPad;
4501           int ii; unsigned char *dstTrav, *srcTrav; /* indices for copying */
4502
4503           /* allocate new image for mipmap of size newRowLength x newheight */
4504           void *newMipmapImage= malloc((size_t) (newRowLength*newheight));
4505           if (newMipmapImage == NULL) {
4506              /* out of memory so return */
4507              glPixelStorei(GL_UNPACK_ALIGNMENT, psm.unpack_alignment);
4508              glPixelStorei(GL_UNPACK_SKIP_ROWS, psm.unpack_skip_rows);
4509              glPixelStorei(GL_UNPACK_SKIP_PIXELS, psm.unpack_skip_pixels);
4510              glPixelStorei(GL_UNPACK_ROW_LENGTH, psm.unpack_row_length);
4511              glPixelStorei(GL_UNPACK_SWAP_BYTES, psm.unpack_swap_bytes);
4512              return GLU_OUT_OF_MEMORY;
4513           }
4514
4515           /* copy image from srcImage into newMipmapImage by rows */
4516           for (ii= 0,
4517                dstTrav= (unsigned char *) newMipmapImage,
4518                srcTrav= (unsigned char *) srcImage;
4519                ii< newheight;
4520                ii++,
4521                dstTrav+= newRowLength, /* make sure the correct distance... */
4522                srcTrav+= rowsize) {    /* ...is skipped */
4523              memcpy(dstTrav,srcTrav,rowsize);
4524              /* note that the pad bytes are not visited and will contain
4525               * garbage, which is ok.
4526               */
4527           }
4528
4529           /* ...and use this new image for mipmapping instead */
4530           if (baseLevel <= level && level <= maxLevel) {
4531           glTexImage2D(target, level, internalFormat, newwidth, newheight, 0,
4532                        format, type, newMipmapImage);
4533           }
4534           free(newMipmapImage); /* don't forget to free it! */
4535        } /* else */
4536       }
4537     } /* for level */
4538     glPixelStorei(GL_UNPACK_ALIGNMENT, psm.unpack_alignment);
4539     glPixelStorei(GL_UNPACK_SKIP_ROWS, psm.unpack_skip_rows);
4540     glPixelStorei(GL_UNPACK_SKIP_PIXELS, psm.unpack_skip_pixels);
4541     glPixelStorei(GL_UNPACK_ROW_LENGTH, psm.unpack_row_length);
4542     glPixelStorei(GL_UNPACK_SWAP_BYTES, psm.unpack_swap_bytes);
4543
4544     free(srcImage); /*if you get to here, a srcImage has always been malloc'ed*/
4545     if (dstImage) { /* if it's non-rectangular and only 1 level */
4546       free(dstImage);
4547     }
4548     return 0;
4549 } /* gluBuild2DMipmapLevelsCore() */
4550
4551 GLint GLAPIENTRY
4552 gluBuild2DMipmapLevels(GLenum target, GLint internalFormat,
4553                              GLsizei width, GLsizei height,
4554                              GLenum format, GLenum type,
4555                              GLint userLevel, GLint baseLevel, GLint maxLevel,
4556                              const void *data)
4557 {
4558    int level, levels;
4559
4560    int rc= checkMipmapArgs(internalFormat,format,type);
4561    if (rc != 0) return rc;
4562
4563    if (width < 1 || height < 1) {
4564        return GLU_INVALID_VALUE;
4565    }
4566
4567    levels = computeLog(width);
4568    level = computeLog(height);
4569    if (level > levels) levels=level;
4570
4571    levels+= userLevel;
4572    if (!isLegalLevels(userLevel,baseLevel,maxLevel,levels))
4573       return GLU_INVALID_VALUE;
4574
4575    return gluBuild2DMipmapLevelsCore(target, internalFormat,
4576                                      width, height,
4577                                      width, height,
4578                                      format, type,
4579                                      userLevel, baseLevel, maxLevel,
4580                                      data);
4581 } /* gluBuild2DMipmapLevels() */
4582
4583 GLint GLAPIENTRY
4584 gluBuild2DMipmaps(GLenum target, GLint internalFormat,
4585                         GLsizei width, GLsizei height,
4586                         GLenum format, GLenum type,
4587                         const void *data)
4588 {
4589    GLint widthPowerOf2, heightPowerOf2;
4590    int level, levels;
4591
4592    int rc= checkMipmapArgs(internalFormat,format,type);
4593    if (rc != 0) return rc;
4594
4595    if (width < 1 || height < 1) {
4596        return GLU_INVALID_VALUE;
4597    }
4598
4599    closestFit(target,width,height,internalFormat,format,type,
4600               &widthPowerOf2,&heightPowerOf2);
4601
4602    levels = computeLog(widthPowerOf2);
4603    level = computeLog(heightPowerOf2);
4604    if (level > levels) levels=level;
4605
4606    return gluBuild2DMipmapLevelsCore(target,internalFormat,
4607                                      width, height,
4608                                      widthPowerOf2,heightPowerOf2,
4609                                      format,type,
4610                                      0,0,levels,data);
4611 }  /* gluBuild2DMipmaps() */
4612
4613 #if 0
4614 /*
4615 ** This routine is for the limited case in which
4616 **      type == GL_UNSIGNED_BYTE && format != index  &&
4617 **      unpack_alignment = 1 && unpack_swap_bytes == false
4618 **
4619 ** so all of the work data can be kept as ubytes instead of shorts.
4620 */
4621 static int fastBuild2DMipmaps(const PixelStorageModes *psm,
4622                        GLenum target, GLint components, GLint width,
4623                      GLint height, GLenum format,
4624                      GLenum type, void *data)
4625 {
4626     GLint newwidth, newheight;
4627     GLint level, levels;
4628     GLubyte *newImage;
4629     GLint newImage_width;
4630     GLint newImage_height;
4631     GLubyte *otherImage;
4632     GLubyte *imageTemp;
4633     GLint memreq;
4634     GLint cmpts;
4635
4636
4637 #if 0
4638     glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxsize);
4639     newwidth = nearestPower(width);
4640     if (newwidth > maxsize) newwidth = maxsize;
4641     newheight = nearestPower(height);
4642     if (newheight > maxsize) newheight = maxsize;
4643 #else
4644     closestFit(target,width,height,components,format,type,
4645                &newwidth,&newheight);
4646 #endif
4647     levels = computeLog(newwidth);
4648     level = computeLog(newheight);
4649     if (level > levels) levels=level;
4650
4651     cmpts = elements_per_group(format,type);
4652
4653     otherImage = NULL;
4654     /**
4655     ** No need to copy the user data if its in the packed correctly.
4656     ** Make sure that later routines don't change that data.
4657     */
4658     if (psm->unpack_skip_rows == 0 && psm->unpack_skip_pixels == 0) {
4659         newImage = (GLubyte *)data;
4660         newImage_width = width;
4661         newImage_height = height;
4662     } else {
4663         GLint rowsize;
4664         GLint groups_per_line;
4665         GLint elements_per_line;
4666         const GLubyte *start;
4667         const GLubyte *iter;
4668         GLubyte *iter2;
4669         GLint i, j;
4670
4671         newImage = (GLubyte *)
4672             malloc(image_size(width, height, format, GL_UNSIGNED_BYTE));
4673         newImage_width = width;
4674         newImage_height = height;
4675         if (newImage == NULL) {
4676             return GLU_OUT_OF_MEMORY;
4677         }
4678
4679         /*
4680         ** Abbreviated version of fill_image for this restricted case.
4681         */
4682         if (psm->unpack_row_length > 0) {
4683             groups_per_line = psm->unpack_row_length;
4684         } else {
4685             groups_per_line = width;
4686         }
4687         rowsize = groups_per_line * cmpts;
4688         elements_per_line = width * cmpts;
4689         start = (const GLubyte *) data + psm->unpack_skip_rows * rowsize +
4690                 psm->unpack_skip_pixels * cmpts;
4691         iter2 = newImage;
4692
4693         for (i = 0; i < height; i++) {
4694             iter = start;
4695             for (j = 0; j < elements_per_line; j++) {
4696                 *iter2 = *iter;
4697                 iter++;
4698                 iter2++;
4699             }
4700             start += rowsize;
4701         }
4702     }
4703
4704
4705     glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
4706     glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
4707     glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
4708     glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
4709     glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE);
4710
4711     for (level = 0; level <= levels; level++) {
4712         if (newImage_width == newwidth && newImage_height == newheight) {
4713             /* Use newImage for this level */
4714             glTexImage2D(target, level, components, newImage_width,
4715                     newImage_height, 0, format, GL_UNSIGNED_BYTE,
4716                     (void *) newImage);
4717         } else {
4718             if (otherImage == NULL) {
4719                 memreq =
4720                     image_size(newwidth, newheight, format, GL_UNSIGNED_BYTE);
4721                 otherImage = (GLubyte *) malloc(memreq);
4722                 if (otherImage == NULL) {
4723                     glPixelStorei(GL_UNPACK_ALIGNMENT, psm->unpack_alignment);
4724                     glPixelStorei(GL_UNPACK_SKIP_ROWS, psm->unpack_skip_rows);
4725                     glPixelStorei(GL_UNPACK_SKIP_PIXELS, psm->unpack_skip_pixels);
4726                     glPixelStorei(GL_UNPACK_ROW_LENGTH,psm->unpack_row_length);
4727                     glPixelStorei(GL_UNPACK_SWAP_BYTES,psm->unpack_swap_bytes);
4728                     return GLU_OUT_OF_MEMORY;
4729                 }
4730             }
4731 /*
4732             scale_internal_ubyte(cmpts, newImage_width, newImage_height,
4733                     newImage, newwidth, newheight, otherImage);
4734 */
4735             /* Swap newImage and otherImage */
4736             imageTemp = otherImage;
4737             otherImage = newImage;
4738             newImage = imageTemp;
4739
4740             newImage_width = newwidth;
4741             newImage_height = newheight;
4742             glTexImage2D(target, level, components, newImage_width,
4743                     newImage_height, 0, format, GL_UNSIGNED_BYTE,
4744                     (void *) newImage);
4745         }
4746         if (newwidth > 1) newwidth /= 2;
4747         if (newheight > 1) newheight /= 2;
4748     }
4749     glPixelStorei(GL_UNPACK_ALIGNMENT, psm->unpack_alignment);
4750     glPixelStorei(GL_UNPACK_SKIP_ROWS, psm->unpack_skip_rows);
4751     glPixelStorei(GL_UNPACK_SKIP_PIXELS, psm->unpack_skip_pixels);
4752     glPixelStorei(GL_UNPACK_ROW_LENGTH, psm->unpack_row_length);
4753     glPixelStorei(GL_UNPACK_SWAP_BYTES, psm->unpack_swap_bytes);
4754
4755     if (newImage != (const GLubyte *)data) {
4756         free((GLbyte *) newImage);
4757     }
4758     if (otherImage && otherImage != (const GLubyte *)data) {
4759         free((GLbyte *) otherImage);
4760     }
4761     return 0;
4762 }
4763 #endif
4764
4765 /*
4766  * Utility Routines
4767  */
4768 static GLint elements_per_group(GLenum format, GLenum type)
4769 {
4770     /*
4771      * Return the number of elements per group of a specified format
4772      */
4773
4774     /* If the type is packedpixels then answer is 1 (ignore format) */
4775     if (type == GL_UNSIGNED_BYTE_3_3_2 ||
4776         type == GL_UNSIGNED_BYTE_2_3_3_REV ||
4777         type == GL_UNSIGNED_SHORT_5_6_5 ||
4778         type == GL_UNSIGNED_SHORT_5_6_5_REV ||
4779         type == GL_UNSIGNED_SHORT_4_4_4_4 ||
4780         type == GL_UNSIGNED_SHORT_4_4_4_4_REV ||
4781         type == GL_UNSIGNED_SHORT_5_5_5_1  ||
4782         type == GL_UNSIGNED_SHORT_1_5_5_5_REV  ||
4783         type == GL_UNSIGNED_INT_8_8_8_8 ||
4784         type == GL_UNSIGNED_INT_8_8_8_8_REV ||
4785         type == GL_UNSIGNED_INT_10_10_10_2 ||
4786         type == GL_UNSIGNED_INT_2_10_10_10_REV) {
4787         return 1;
4788     }
4789
4790     /* Types are not packed pixels, so get elements per group */
4791     switch(format) {
4792       case GL_RGB:
4793       case GL_BGR:
4794         return 3;
4795       case GL_LUMINANCE_ALPHA:
4796         return 2;
4797       case GL_RGBA:
4798       case GL_BGRA:
4799         return 4;
4800       default:
4801         return 1;
4802     }
4803 }
4804
4805 static GLfloat bytes_per_element(GLenum type)
4806 {
4807     /*
4808      * Return the number of bytes per element, based on the element type
4809      */
4810     switch(type) {
4811       case GL_BITMAP:
4812         return 1.0 / 8.0;
4813       case GL_UNSIGNED_SHORT:
4814         return(sizeof(GLushort));
4815       case GL_SHORT:
4816         return(sizeof(GLshort));
4817       case GL_UNSIGNED_BYTE:
4818         return(sizeof(GLubyte));
4819       case GL_BYTE:
4820         return(sizeof(GLbyte));
4821       case GL_INT:
4822         return(sizeof(GLint));
4823       case GL_UNSIGNED_INT:
4824         return(sizeof(GLuint));
4825       case GL_FLOAT:
4826         return(sizeof(GLfloat));
4827       case GL_UNSIGNED_BYTE_3_3_2:
4828       case GL_UNSIGNED_BYTE_2_3_3_REV:  
4829         return(sizeof(GLubyte));
4830       case GL_UNSIGNED_SHORT_5_6_5:
4831       case GL_UNSIGNED_SHORT_5_6_5_REV:
4832       case GL_UNSIGNED_SHORT_4_4_4_4:
4833       case GL_UNSIGNED_SHORT_4_4_4_4_REV:
4834       case GL_UNSIGNED_SHORT_5_5_5_1:
4835       case GL_UNSIGNED_SHORT_1_5_5_5_REV:
4836         return(sizeof(GLushort));
4837       case GL_UNSIGNED_INT_8_8_8_8:
4838       case GL_UNSIGNED_INT_8_8_8_8_REV:
4839       case GL_UNSIGNED_INT_10_10_10_2:
4840       case GL_UNSIGNED_INT_2_10_10_10_REV:
4841         return(sizeof(GLuint));
4842       default:
4843         return 4;
4844     }
4845 }
4846
4847 static GLint is_index(GLenum format)
4848 {
4849     return format == GL_COLOR_INDEX || format == GL_STENCIL_INDEX;
4850 }
4851
4852 /*
4853 ** Compute memory required for internal packed array of data of given type
4854 ** and format.
4855 */
4856 static GLint image_size(GLint width, GLint height, GLenum format, GLenum type)
4857 {
4858     int bytes_per_row;
4859     int components;
4860
4861 assert(width > 0);
4862 assert(height > 0);
4863     components = elements_per_group(format,type);
4864     if (type == GL_BITMAP) {
4865         bytes_per_row = (width + 7) / 8;
4866     } else {
4867         bytes_per_row = bytes_per_element(type) * width;
4868     }
4869     return bytes_per_row * height * components;
4870 }
4871
4872 /*
4873 ** Extract array from user's data applying all pixel store modes.
4874 ** The internal format used is an array of unsigned shorts.
4875 */
4876 static void fill_image(const PixelStorageModes *psm,
4877                        GLint width, GLint height, GLenum format,
4878                        GLenum type, GLboolean index_format,
4879                        const void *userdata, GLushort *newimage)
4880 {
4881     GLint components;
4882     GLint element_size;
4883     GLint rowsize;
4884     GLint padding;
4885     GLint groups_per_line;
4886     GLint group_size;
4887     GLint elements_per_line;
4888     const GLubyte *start;
4889     const GLubyte *iter;
4890     GLushort *iter2;
4891     GLint i, j, k;
4892     GLint myswap_bytes;
4893
4894     myswap_bytes = psm->unpack_swap_bytes;
4895     components = elements_per_group(format,type);
4896     if (psm->unpack_row_length > 0) {
4897         groups_per_line = psm->unpack_row_length;
4898     } else {
4899         groups_per_line = width;
4900     }
4901
4902     /* All formats except GL_BITMAP fall out trivially */
4903     if (type == GL_BITMAP) {
4904         GLint bit_offset;
4905         GLint current_bit;
4906
4907         rowsize = (groups_per_line * components + 7) / 8;
4908         padding = (rowsize % psm->unpack_alignment);
4909         if (padding) {
4910             rowsize += psm->unpack_alignment - padding;
4911         }
4912         start = (const GLubyte *) userdata + psm->unpack_skip_rows * rowsize +
4913                 (psm->unpack_skip_pixels * components / 8);
4914         elements_per_line = width * components;
4915         iter2 = newimage;
4916         for (i = 0; i < height; i++) {
4917             iter = start;
4918             bit_offset = (psm->unpack_skip_pixels * components) % 8;
4919             for (j = 0; j < elements_per_line; j++) {
4920                 /* Retrieve bit */
4921                 if (psm->unpack_lsb_first) {
4922                     current_bit = iter[0] & (1 << bit_offset);
4923                 } else {
4924                     current_bit = iter[0] & (1 << (7 - bit_offset));
4925                 }
4926                 if (current_bit) {
4927                     if (index_format) {
4928                         *iter2 = 1;
4929                     } else {
4930                         *iter2 = 65535;
4931                     }
4932                 } else {
4933                     *iter2 = 0;
4934                 }
4935                 bit_offset++;
4936                 if (bit_offset == 8) {
4937                     bit_offset = 0;
4938                     iter++;
4939                 }
4940                 iter2++;
4941             }
4942             start += rowsize;
4943         }
4944     } else {
4945         element_size = bytes_per_element(type);
4946         group_size = element_size * components;
4947         if (element_size == 1) myswap_bytes = 0;
4948
4949         rowsize = groups_per_line * group_size;
4950         padding = (rowsize % psm->unpack_alignment);
4951         if (padding) {
4952             rowsize += psm->unpack_alignment - padding;
4953         }
4954         start = (const GLubyte *) userdata + psm->unpack_skip_rows * rowsize +
4955                 psm->unpack_skip_pixels * group_size;
4956         elements_per_line = width * components;
4957
4958         iter2 = newimage;
4959         for (i = 0; i < height; i++) {
4960             iter = start;
4961             for (j = 0; j < elements_per_line; j++) {
4962                 Type_Widget widget;
4963                 float extractComponents[4];
4964
4965                 switch(type) {
4966                   case GL_UNSIGNED_BYTE_3_3_2:
4967                     extract332(0,iter,extractComponents);
4968                     for (k = 0; k < 3; k++) {
4969                       *iter2++ = (GLushort)(extractComponents[k]*65535);
4970                     }
4971                     break;
4972                   case GL_UNSIGNED_BYTE_2_3_3_REV:
4973                     extract233rev(0,iter,extractComponents);
4974                     for (k = 0; k < 3; k++) {
4975                       *iter2++ = (GLushort)(extractComponents[k]*65535);
4976                     }
4977                     break;
4978                   case GL_UNSIGNED_BYTE:
4979                     if (index_format) {
4980                         *iter2++ = *iter;
4981                     } else {
4982                         *iter2++ = (*iter) * 257;
4983                     }
4984                     break;
4985                   case GL_BYTE:
4986                     if (index_format) {
4987                         *iter2++ = *((const GLbyte *) iter);
4988                     } else {
4989                         /* rough approx */
4990                         *iter2++ = (*((const GLbyte *) iter)) * 516;
4991                     }
4992                     break;
4993                   case GL_UNSIGNED_SHORT_5_6_5:                         
4994                     extract565(myswap_bytes,iter,extractComponents);
4995                     for (k = 0; k < 3; k++) {
4996                       *iter2++ = (GLushort)(extractComponents[k]*65535);
4997                     }
4998                     break;
4999                   case GL_UNSIGNED_SHORT_5_6_5_REV:                     
5000                     extract565rev(myswap_bytes,iter,extractComponents);
5001                     for (k = 0; k < 3; k++) {
5002                       *iter2++ = (GLushort)(extractComponents[k]*65535);
5003                     }
5004                     break;
5005                   case GL_UNSIGNED_SHORT_4_4_4_4:               
5006                     extract4444(myswap_bytes,iter,extractComponents);
5007                     for (k = 0; k < 4; k++) {
5008                       *iter2++ = (GLushort)(extractComponents[k]*65535);
5009                     }
5010                     break;
5011                   case GL_UNSIGNED_SHORT_4_4_4_4_REV:           
5012                     extract4444rev(myswap_bytes,iter,extractComponents);
5013                     for (k = 0; k < 4; k++) {
5014                       *iter2++ = (GLushort)(extractComponents[k]*65535);
5015                     }
5016                     break;
5017                   case GL_UNSIGNED_SHORT_5_5_5_1:               
5018                     extract5551(myswap_bytes,iter,extractComponents);
5019                     for (k = 0; k < 4; k++) {
5020                       *iter2++ = (GLushort)(extractComponents[k]*65535);
5021                     }
5022                     break;
5023                   case GL_UNSIGNED_SHORT_1_5_5_5_REV:
5024                     extract1555rev(myswap_bytes,iter,extractComponents);
5025                     for (k = 0; k < 4; k++) {
5026                       *iter2++ = (GLushort)(extractComponents[k]*65535);
5027                     }
5028                     break;
5029                   case GL_UNSIGNED_SHORT:
5030                   case GL_SHORT:
5031                     if (myswap_bytes) {
5032                         widget.ub[0] = iter[1];
5033                         widget.ub[1] = iter[0];
5034                     } else {
5035                         widget.ub[0] = iter[0];
5036                         widget.ub[1] = iter[1];
5037                     }
5038                     if (type == GL_SHORT) {
5039                         if (index_format) {
5040                             *iter2++ = widget.s[0];
5041                         } else {
5042                             /* rough approx */
5043                             *iter2++ = widget.s[0]*2;
5044                         }
5045                     } else {
5046                         *iter2++ = widget.us[0];
5047                     }
5048                     break;
5049                   case GL_UNSIGNED_INT_8_8_8_8:         
5050                     extract8888(myswap_bytes,iter,extractComponents);
5051                     for (k = 0; k < 4; k++) {
5052                       *iter2++ = (GLushort)(extractComponents[k]*65535);
5053                     }
5054                     break;
5055                   case GL_UNSIGNED_INT_8_8_8_8_REV:             
5056                     extract8888rev(myswap_bytes,iter,extractComponents);
5057                     for (k = 0; k < 4; k++) {
5058                       *iter2++ = (GLushort)(extractComponents[k]*65535);
5059                     }
5060                     break;
5061                   case GL_UNSIGNED_INT_10_10_10_2:              
5062                     extract1010102(myswap_bytes,iter,extractComponents);
5063                     for (k = 0; k < 4; k++) {
5064                       *iter2++ = (GLushort)(extractComponents[k]*65535);
5065                     }
5066                     break;
5067                   case GL_UNSIGNED_INT_2_10_10_10_REV:
5068                     extract2101010rev(myswap_bytes,iter,extractComponents);
5069                     for (k = 0; k < 4; k++) {
5070                       *iter2++ = (GLushort)(extractComponents[k]*65535);
5071                     }
5072                     break;
5073                   case GL_INT:
5074                   case GL_UNSIGNED_INT:
5075                   case GL_FLOAT:
5076                     if (myswap_bytes) {
5077                         widget.ub[0] = iter[3];
5078                         widget.ub[1] = iter[2];
5079                         widget.ub[2] = iter[1];
5080                         widget.ub[3] = iter[0];
5081                     } else {
5082                         widget.ub[0] = iter[0];
5083                         widget.ub[1] = iter[1];
5084                         widget.ub[2] = iter[2];
5085                         widget.ub[3] = iter[3];
5086                     }
5087                     if (type == GL_FLOAT) {
5088                         if (index_format) {
5089                             *iter2++ = widget.f;
5090                         } else {
5091                             *iter2++ = 65535 * widget.f;
5092                         }
5093                     } else if (type == GL_UNSIGNED_INT) {
5094                         if (index_format) {
5095                             *iter2++ = widget.ui;
5096                         } else {
5097                             *iter2++ = widget.ui >> 16;
5098                         }
5099                     } else {
5100                         if (index_format) {
5101                             *iter2++ = widget.i;
5102                         } else {
5103                             *iter2++ = widget.i >> 15;
5104                         }
5105                     }
5106                     break;
5107                 }
5108                 iter += element_size;
5109             } /* for j */
5110             start += rowsize;
5111 #if 1
5112             /* want 'iter' pointing at start, not within, row for assertion
5113              * purposes
5114              */
5115             iter= start;        
5116 #endif
5117         } /* for i */
5118
5119        /* iterators should be one byte past end */
5120        if (!isTypePackedPixel(type)) {
5121           assert(iter2 == &newimage[width*height*components]);
5122        }
5123        else {
5124           assert(iter2 == &newimage[width*height*
5125                                     elements_per_group(format,0)]);
5126        }
5127        assert( iter == &((const GLubyte *)userdata)[rowsize*height +
5128                                         psm->unpack_skip_rows * rowsize +
5129                                         psm->unpack_skip_pixels * group_size] );
5130
5131     } /* else */
5132 } /* fill_image() */
5133
5134 /*
5135 ** Insert array into user's data applying all pixel store modes.
5136 ** The internal format is an array of unsigned shorts.
5137 ** empty_image() because it is the opposite of fill_image().
5138 */
5139 static void empty_image(const PixelStorageModes *psm,
5140                         GLint width, GLint height, GLenum format,
5141                         GLenum type, GLboolean index_format,
5142                         const GLushort *oldimage, void *userdata)
5143 {
5144     GLint components;
5145     GLint element_size;
5146     GLint rowsize;
5147     GLint padding;
5148     GLint groups_per_line;
5149     GLint group_size;
5150     GLint elements_per_line;
5151     GLubyte *start;
5152     GLubyte *iter;
5153     const GLushort *iter2;
5154     GLint i, j, k;
5155     GLint myswap_bytes;
5156
5157     myswap_bytes = psm->pack_swap_bytes;
5158     components = elements_per_group(format,type);
5159     if (psm->pack_row_length > 0) {
5160         groups_per_line = psm->pack_row_length;
5161     } else {
5162         groups_per_line = width;
5163     }
5164
5165     /* All formats except GL_BITMAP fall out trivially */
5166     if (type == GL_BITMAP) {
5167         GLint bit_offset;
5168         GLint current_bit;
5169
5170         rowsize = (groups_per_line * components + 7) / 8;
5171         padding = (rowsize % psm->pack_alignment);
5172         if (padding) {
5173             rowsize += psm->pack_alignment - padding;
5174         }
5175         start = (GLubyte *) userdata + psm->pack_skip_rows * rowsize +
5176                 (psm->pack_skip_pixels * components / 8);
5177         elements_per_line = width * components;
5178         iter2 = oldimage;
5179         for (i = 0; i < height; i++) {
5180             iter = start;
5181             bit_offset = (psm->pack_skip_pixels * components) % 8;
5182             for (j = 0; j < elements_per_line; j++) {
5183                 if (index_format) {
5184                     current_bit = iter2[0] & 1;
5185                 } else {
5186                     if (iter2[0] > 32767) {
5187                         current_bit = 1;
5188                     } else {
5189                         current_bit = 0;
5190                     }
5191                 }
5192
5193                 if (current_bit) {
5194                     if (psm->pack_lsb_first) {
5195                         *iter |= (1 << bit_offset);
5196                     } else {
5197                         *iter |= (1 << (7 - bit_offset));
5198                     }
5199                 } else {
5200                     if (psm->pack_lsb_first) {
5201                         *iter &= ~(1 << bit_offset);
5202                     } else {
5203                         *iter &= ~(1 << (7 - bit_offset));
5204                     }
5205                 }
5206
5207                 bit_offset++;
5208                 if (bit_offset == 8) {
5209                     bit_offset = 0;
5210                     iter++;
5211                 }
5212                 iter2++;
5213             }
5214             start += rowsize;
5215         }
5216     } else {
5217         float shoveComponents[4];
5218
5219         element_size = bytes_per_element(type);
5220         group_size = element_size * components;
5221         if (element_size == 1) myswap_bytes = 0;
5222
5223         rowsize = groups_per_line * group_size;
5224         padding = (rowsize % psm->pack_alignment);
5225         if (padding) {
5226             rowsize += psm->pack_alignment - padding;
5227         }
5228         start = (GLubyte *) userdata + psm->pack_skip_rows * rowsize +
5229                 psm->pack_skip_pixels * group_size;
5230         elements_per_line = width * components;
5231
5232         iter2 = oldimage;
5233         for (i = 0; i < height; i++) {
5234             iter = start;
5235             for (j = 0; j < elements_per_line; j++) {
5236                 Type_Widget widget;
5237
5238                 switch(type) {
5239                   case GL_UNSIGNED_BYTE_3_3_2:
5240                     for (k = 0; k < 3; k++) {
5241                        shoveComponents[k]= *iter2++ / 65535.0;
5242                     }
5243                     shove332(shoveComponents,0,(void *)iter);
5244                     break;
5245                   case GL_UNSIGNED_BYTE_2_3_3_REV:
5246                     for (k = 0; k < 3; k++) {
5247                        shoveComponents[k]= *iter2++ / 65535.0;
5248                     }
5249                     shove233rev(shoveComponents,0,(void *)iter);
5250                     break;
5251                   case GL_UNSIGNED_BYTE:
5252                     if (index_format) {
5253                         *iter = *iter2++;
5254                     } else {
5255                         *iter = *iter2++ >> 8;
5256                     }
5257                     break;
5258                   case GL_BYTE:
5259                     if (index_format) {
5260                         *((GLbyte *) iter) = *iter2++;
5261                     } else {
5262                         *((GLbyte *) iter) = *iter2++ >> 9;
5263                     }
5264                     break;
5265                   case GL_UNSIGNED_SHORT_5_6_5:         
5266                     for (k = 0; k < 3; k++) {
5267                        shoveComponents[k]= *iter2++ / 65535.0;
5268                     }
5269                     shove565(shoveComponents,0,(void *)&widget.us[0]);
5270                     if (myswap_bytes) {
5271                        iter[0] = widget.ub[1];
5272                        iter[1] = widget.ub[0];
5273                     }
5274                     else {
5275                        *(GLushort *)iter = widget.us[0];
5276                     }
5277                     break;
5278                   case GL_UNSIGNED_SHORT_5_6_5_REV:             
5279                     for (k = 0; k < 3; k++) {
5280                        shoveComponents[k]= *iter2++ / 65535.0;
5281                     }
5282                     shove565rev(shoveComponents,0,(void *)&widget.us[0]);
5283                     if (myswap_bytes) {
5284                        iter[0] = widget.ub[1];
5285                        iter[1] = widget.ub[0];
5286                     }
5287                     else {
5288                        *(GLushort *)iter = widget.us[0];
5289                     }
5290                     break;
5291                   case GL_UNSIGNED_SHORT_4_4_4_4:
5292                     for (k = 0; k < 4; k++) {
5293                        shoveComponents[k]= *iter2++ / 65535.0;
5294                     }
5295                     shove4444(shoveComponents,0,(void *)&widget.us[0]);
5296                     if (myswap_bytes) {
5297                        iter[0] = widget.ub[1];
5298                        iter[1] = widget.ub[0];
5299                     } else {
5300                        *(GLushort *)iter = widget.us[0];
5301                     }
5302                     break;
5303                   case GL_UNSIGNED_SHORT_4_4_4_4_REV:
5304                     for (k = 0; k < 4; k++) {
5305                        shoveComponents[k]= *iter2++ / 65535.0;
5306                     }
5307                     shove4444rev(shoveComponents,0,(void *)&widget.us[0]);
5308                     if (myswap_bytes) {
5309                        iter[0] = widget.ub[1];
5310                        iter[1] = widget.ub[0];
5311                     } else {
5312                        *(GLushort *)iter = widget.us[0];
5313                     }
5314                     break;
5315                   case GL_UNSIGNED_SHORT_5_5_5_1:
5316                     for (k = 0; k < 4; k++) {
5317                        shoveComponents[k]= *iter2++ / 65535.0;
5318                     }
5319                     shove5551(shoveComponents,0,(void *)&widget.us[0]);
5320                     if (myswap_bytes) {
5321                        iter[0] = widget.ub[1];
5322                        iter[1] = widget.ub[0];
5323                     } else {
5324                        *(GLushort *)iter = widget.us[0];
5325                     }
5326                     break;
5327                   case GL_UNSIGNED_SHORT_1_5_5_5_REV:
5328                     for (k = 0; k < 4; k++) {
5329                        shoveComponents[k]= *iter2++ / 65535.0;
5330                     }
5331                     shove1555rev(shoveComponents,0,(void *)&widget.us[0]);
5332                     if (myswap_bytes) {
5333                        iter[0] = widget.ub[1];
5334                        iter[1] = widget.ub[0];
5335                     } else {
5336                        *(GLushort *)iter = widget.us[0];
5337                     }
5338                     break;
5339                   case GL_UNSIGNED_SHORT:
5340                   case GL_SHORT:
5341                     if (type == GL_SHORT) {
5342                         if (index_format) {
5343                             widget.s[0] = *iter2++;
5344                         } else {
5345                             widget.s[0] = *iter2++ >> 1;
5346                         }
5347                     } else {
5348                         widget.us[0] = *iter2++;
5349                     }
5350                     if (myswap_bytes) {
5351                         iter[0] = widget.ub[1];
5352                         iter[1] = widget.ub[0];
5353                     } else {
5354                         iter[0] = widget.ub[0];
5355                         iter[1] = widget.ub[1];
5356                     }
5357                     break;
5358                   case GL_UNSIGNED_INT_8_8_8_8:
5359                     for (k = 0; k < 4; k++) {
5360                        shoveComponents[k]= *iter2++ / 65535.0;
5361                     }
5362                     shove8888(shoveComponents,0,(void *)&widget.ui);
5363                     if (myswap_bytes) {
5364                         iter[3] = widget.ub[0];
5365                         iter[2] = widget.ub[1];
5366                         iter[1] = widget.ub[2];
5367                         iter[0] = widget.ub[3];
5368                     } else {
5369                         *(GLuint *)iter= widget.ui;
5370                     }
5371
5372                     break;
5373                   case GL_UNSIGNED_INT_8_8_8_8_REV:
5374                     for (k = 0; k < 4; k++) {
5375                        shoveComponents[k]= *iter2++ / 65535.0;
5376                     }
5377                     shove8888rev(shoveComponents,0,(void *)&widget.ui);
5378                     if (myswap_bytes) {
5379                         iter[3] = widget.ub[0];
5380                         iter[2] = widget.ub[1];
5381                         iter[1] = widget.ub[2];
5382                         iter[0] = widget.ub[3];
5383                     } else {
5384                         *(GLuint *)iter= widget.ui;
5385                     }
5386                     break;
5387                   case GL_UNSIGNED_INT_10_10_10_2:
5388                     for (k = 0; k < 4; k++) {
5389                        shoveComponents[k]= *iter2++ / 65535.0;
5390                     }
5391                     shove1010102(shoveComponents,0,(void *)&widget.ui);
5392                     if (myswap_bytes) {
5393                         iter[3] = widget.ub[0];
5394                         iter[2] = widget.ub[1];
5395                         iter[1] = widget.ub[2];
5396                         iter[0] = widget.ub[3];
5397                     } else {
5398                         *(GLuint *)iter= widget.ui;
5399                     }
5400                     break;
5401                   case GL_UNSIGNED_INT_2_10_10_10_REV:
5402                     for (k = 0; k < 4; k++) {
5403                        shoveComponents[k]= *iter2++ / 65535.0;
5404                     }
5405                     shove2101010rev(shoveComponents,0,(void *)&widget.ui);
5406                     if (myswap_bytes) {
5407                         iter[3] = widget.ub[0];
5408                         iter[2] = widget.ub[1];
5409                         iter[1] = widget.ub[2];
5410                         iter[0] = widget.ub[3];
5411                     } else {
5412                         *(GLuint *)iter= widget.ui;
5413                     }
5414                     break;
5415                   case GL_INT:
5416                   case GL_UNSIGNED_INT:
5417                   case GL_FLOAT:
5418                     if (type == GL_FLOAT) {
5419                         if (index_format) {
5420                             widget.f = *iter2++;
5421                         } else {
5422                             widget.f = *iter2++ / (float) 65535.0;
5423                         }
5424                     } else if (type == GL_UNSIGNED_INT) {
5425                         if (index_format) {
5426                             widget.ui = *iter2++;
5427                         } else {
5428                             widget.ui = (unsigned int) *iter2++ * 65537;
5429                         }
5430                     } else {
5431                         if (index_format) {
5432                             widget.i = *iter2++;
5433                         } else {
5434                             widget.i = ((unsigned int) *iter2++ * 65537)/2;
5435                         }
5436                     }
5437                     if (myswap_bytes) {
5438                         iter[3] = widget.ub[0];
5439                         iter[2] = widget.ub[1];
5440                         iter[1] = widget.ub[2];
5441                         iter[0] = widget.ub[3];
5442                     } else {
5443                         iter[0] = widget.ub[0];
5444                         iter[1] = widget.ub[1];
5445                         iter[2] = widget.ub[2];
5446                         iter[3] = widget.ub[3];
5447                     }
5448                     break;
5449                 }
5450                 iter += element_size;
5451             } /* for j */
5452             start += rowsize;
5453 #if 1
5454             /* want 'iter' pointing at start, not within, row for assertion
5455              * purposes
5456              */
5457             iter= start;        
5458 #endif
5459         } /* for i */
5460
5461         /* iterators should be one byte past end */
5462         if (!isTypePackedPixel(type)) {
5463            assert(iter2 == &oldimage[width*height*components]);
5464         }
5465         else {
5466            assert(iter2 == &oldimage[width*height*
5467                                      elements_per_group(format,0)]);
5468         }
5469         assert( iter == &((GLubyte *)userdata)[rowsize*height +
5470                                         psm->pack_skip_rows * rowsize +
5471                                         psm->pack_skip_pixels * group_size] );
5472
5473     } /* else */
5474 } /* empty_image() */
5475
5476 /*--------------------------------------------------------------------------
5477  * Decimation of packed pixel types
5478  *--------------------------------------------------------------------------
5479  */
5480 static void extract332(int isSwap,
5481                        const void *packedPixel, GLfloat extractComponents[])
5482 {
5483    GLubyte ubyte= *(const GLubyte *)packedPixel;
5484
5485    isSwap= isSwap;              /* turn off warnings */
5486
5487    /* 11100000 == 0xe0 */
5488    /* 00011100 == 0x1c */
5489    /* 00000011 == 0x03 */
5490
5491    extractComponents[0]=   (float)((ubyte & 0xe0)  >> 5) / 7.0;
5492    extractComponents[1]=   (float)((ubyte & 0x1c)  >> 2) / 7.0; /* 7 = 2^3-1 */
5493    extractComponents[2]=   (float)((ubyte & 0x03)      ) / 3.0; /* 3 = 2^2-1 */
5494 } /* extract332() */
5495
5496 static void shove332(const GLfloat shoveComponents[],
5497                      int index, void *packedPixel)      
5498 {
5499    /* 11100000 == 0xe0 */
5500    /* 00011100 == 0x1c */
5501    /* 00000011 == 0x03 */
5502
5503    assert(0.0 <= shoveComponents[0] && shoveComponents[0] <= 1.0);
5504    assert(0.0 <= shoveComponents[1] && shoveComponents[1] <= 1.0);
5505    assert(0.0 <= shoveComponents[2] && shoveComponents[2] <= 1.0);
5506
5507    /* due to limited precision, need to round before shoving */
5508    ((GLubyte *)packedPixel)[index]  =
5509      ((GLubyte)((shoveComponents[0] * 7)+0.5)  << 5) & 0xe0;
5510    ((GLubyte *)packedPixel)[index] |=
5511      ((GLubyte)((shoveComponents[1] * 7)+0.5)  << 2) & 0x1c;
5512    ((GLubyte *)packedPixel)[index]  |=
5513      ((GLubyte)((shoveComponents[2] * 3)+0.5)      ) & 0x03;
5514 } /* shove332() */
5515
5516 static void extract233rev(int isSwap,
5517                           const void *packedPixel, GLfloat extractComponents[])
5518 {
5519    GLubyte ubyte= *(const GLubyte *)packedPixel;
5520
5521    isSwap= isSwap;              /* turn off warnings */
5522
5523    /* 0000,0111 == 0x07 */
5524    /* 0011,1000 == 0x38 */
5525    /* 1100,0000 == 0xC0 */
5526
5527    extractComponents[0]= (float)((ubyte & 0x07)     ) / 7.0;
5528    extractComponents[1]= (float)((ubyte & 0x38) >> 3) / 7.0;
5529    extractComponents[2]= (float)((ubyte & 0xC0) >> 6) / 3.0;
5530 } /* extract233rev() */
5531
5532 static void shove233rev(const GLfloat shoveComponents[],
5533                         int index, void *packedPixel)   
5534 {
5535    /* 0000,0111 == 0x07 */
5536    /* 0011,1000 == 0x38 */
5537    /* 1100,0000 == 0xC0 */
5538
5539    assert(0.0 <= shoveComponents[0] && shoveComponents[0] <= 1.0);
5540    assert(0.0 <= shoveComponents[1] && shoveComponents[1] <= 1.0);
5541    assert(0.0 <= shoveComponents[2] && shoveComponents[2] <= 1.0);
5542
5543    /* due to limited precision, need to round before shoving */
5544    ((GLubyte *)packedPixel)[index] =
5545      ((GLubyte)((shoveComponents[0] * 7.0)+0.5)     ) & 0x07;
5546    ((GLubyte *)packedPixel)[index]|=
5547      ((GLubyte)((shoveComponents[1] * 7.0)+0.5) << 3) & 0x38;
5548    ((GLubyte *)packedPixel)[index]|=
5549      ((GLubyte)((shoveComponents[2] * 3.0)+0.5) << 6) & 0xC0;
5550 } /* shove233rev() */
5551
5552 static void extract565(int isSwap,
5553                        const void *packedPixel, GLfloat extractComponents[])
5554 {
5555    GLushort ushort= *(const GLushort *)packedPixel;
5556
5557    if (isSwap) {
5558      ushort= __GLU_SWAP_2_BYTES(packedPixel);
5559    }
5560    else {
5561      ushort= *(const GLushort *)packedPixel;
5562    }
5563
5564    /* 11111000,00000000 == 0xf800 */
5565    /* 00000111,11100000 == 0x07e0 */
5566    /* 00000000,00011111 == 0x001f */
5567
5568    extractComponents[0]=(float)((ushort & 0xf800) >> 11) / 31.0;/* 31 = 2^5-1*/
5569    extractComponents[1]=(float)((ushort & 0x07e0) >>  5) / 63.0;/* 63 = 2^6-1*/
5570    extractComponents[2]=(float)((ushort & 0x001f)      ) / 31.0;
5571 } /* extract565() */
5572
5573 static void shove565(const GLfloat shoveComponents[],
5574                      int index,void *packedPixel)
5575 {
5576    /* 11111000,00000000 == 0xf800 */
5577    /* 00000111,11100000 == 0x07e0 */
5578    /* 00000000,00011111 == 0x001f */
5579
5580    assert(0.0 <= shoveComponents[0] && shoveComponents[0] <= 1.0);
5581    assert(0.0 <= shoveComponents[1] && shoveComponents[1] <= 1.0);
5582    assert(0.0 <= shoveComponents[2] && shoveComponents[2] <= 1.0);
5583
5584    /* due to limited precision, need to round before shoving */
5585    ((GLushort *)packedPixel)[index] =
5586      ((GLushort)((shoveComponents[0] * 31)+0.5) << 11) & 0xf800;
5587    ((GLushort *)packedPixel)[index]|=
5588      ((GLushort)((shoveComponents[1] * 63)+0.5) <<  5) & 0x07e0;
5589    ((GLushort *)packedPixel)[index]|=
5590      ((GLushort)((shoveComponents[2] * 31)+0.5)      ) & 0x001f;
5591 } /* shove565() */
5592
5593 static void extract565rev(int isSwap,
5594                           const void *packedPixel, GLfloat extractComponents[])
5595 {
5596    GLushort ushort= *(const GLushort *)packedPixel;
5597
5598    if (isSwap) {
5599      ushort= __GLU_SWAP_2_BYTES(packedPixel);
5600    }
5601    else {
5602      ushort= *(const GLushort *)packedPixel;
5603    }
5604
5605    /* 00000000,00011111 == 0x001f */
5606    /* 00000111,11100000 == 0x07e0 */
5607    /* 11111000,00000000 == 0xf800 */
5608
5609    extractComponents[0]= (float)((ushort & 0x001F)      ) / 31.0;
5610    extractComponents[1]= (float)((ushort & 0x07E0) >>  5) / 63.0;
5611    extractComponents[2]= (float)((ushort & 0xF800) >> 11) / 31.0;
5612 } /* extract565rev() */
5613
5614 static void shove565rev(const GLfloat shoveComponents[],
5615                         int index,void *packedPixel)
5616 {
5617    /* 00000000,00011111 == 0x001f */
5618    /* 00000111,11100000 == 0x07e0 */
5619    /* 11111000,00000000 == 0xf800 */
5620
5621    assert(0.0 <= shoveComponents[0] && shoveComponents[0] <= 1.0);
5622    assert(0.0 <= shoveComponents[1] && shoveComponents[1] <= 1.0);
5623    assert(0.0 <= shoveComponents[2] && shoveComponents[2] <= 1.0);
5624
5625    /* due to limited precision, need to round before shoving */
5626    ((GLushort *)packedPixel)[index] =
5627      ((GLushort)((shoveComponents[0] * 31.0)+0.5)      ) & 0x001F;
5628    ((GLushort *)packedPixel)[index]|=
5629      ((GLushort)((shoveComponents[1] * 63.0)+0.5) <<  5) & 0x07E0;
5630    ((GLushort *)packedPixel)[index]|=
5631      ((GLushort)((shoveComponents[2] * 31.0)+0.5) << 11) & 0xF800;
5632 } /* shove565rev() */
5633
5634 static void extract4444(int isSwap,const void *packedPixel,
5635                         GLfloat extractComponents[])
5636 {
5637    GLushort ushort;
5638
5639    if (isSwap) {
5640      ushort= __GLU_SWAP_2_BYTES(packedPixel);
5641    }
5642    else {
5643      ushort= *(const GLushort *)packedPixel;
5644    }
5645
5646    /* 11110000,00000000 == 0xf000 */
5647    /* 00001111,00000000 == 0x0f00 */
5648    /* 00000000,11110000 == 0x00f0 */
5649    /* 00000000,00001111 == 0x000f */
5650
5651    extractComponents[0]= (float)((ushort & 0xf000) >> 12) / 15.0;/* 15=2^4-1 */
5652    extractComponents[1]= (float)((ushort & 0x0f00) >>  8) / 15.0;
5653    extractComponents[2]= (float)((ushort & 0x00f0) >>  4) / 15.0;
5654    extractComponents[3]= (float)((ushort & 0x000f)      ) / 15.0;
5655 } /* extract4444() */
5656
5657 static void shove4444(const GLfloat shoveComponents[],
5658                       int index,void *packedPixel)
5659 {
5660    assert(0.0 <= shoveComponents[0] && shoveComponents[0] <= 1.0);
5661    assert(0.0 <= shoveComponents[1] && shoveComponents[1] <= 1.0);
5662    assert(0.0 <= shoveComponents[2] && shoveComponents[2] <= 1.0);
5663    assert(0.0 <= shoveComponents[3] && shoveComponents[3] <= 1.0);
5664
5665    /* due to limited precision, need to round before shoving */
5666    ((GLushort *)packedPixel)[index] =
5667      ((GLushort)((shoveComponents[0] * 15)+0.5) << 12) & 0xf000;
5668    ((GLushort *)packedPixel)[index]|=
5669      ((GLushort)((shoveComponents[1] * 15)+0.5) <<  8) & 0x0f00;
5670    ((GLushort *)packedPixel)[index]|=
5671      ((GLushort)((shoveComponents[2] * 15)+0.5) <<  4) & 0x00f0;
5672    ((GLushort *)packedPixel)[index]|=
5673      ((GLushort)((shoveComponents[3] * 15)+0.5)      ) & 0x000f;
5674 } /* shove4444() */
5675
5676 static void extract4444rev(int isSwap,const void *packedPixel,
5677                            GLfloat extractComponents[])
5678 {
5679    GLushort ushort;
5680
5681    if (isSwap) {
5682      ushort= __GLU_SWAP_2_BYTES(packedPixel);
5683    }
5684    else {
5685      ushort= *(const GLushort *)packedPixel;
5686    }
5687
5688    /* 00000000,00001111 == 0x000f */
5689    /* 00000000,11110000 == 0x00f0 */
5690    /* 00001111,00000000 == 0x0f00 */
5691    /* 11110000,00000000 == 0xf000 */
5692
5693    /* 15 = 2^4-1 */
5694    extractComponents[0]= (float)((ushort & 0x000F)      ) / 15.0;
5695    extractComponents[1]= (float)((ushort & 0x00F0) >>  4) / 15.0;
5696    extractComponents[2]= (float)((ushort & 0x0F00) >>  8) / 15.0;
5697    extractComponents[3]= (float)((ushort & 0xF000) >> 12) / 15.0;
5698 } /* extract4444rev() */
5699
5700 static void shove4444rev(const GLfloat shoveComponents[],
5701                          int index,void *packedPixel)
5702 {
5703    /* 00000000,00001111 == 0x000f */
5704    /* 00000000,11110000 == 0x00f0 */
5705    /* 00001111,00000000 == 0x0f00 */
5706    /* 11110000,00000000 == 0xf000 */
5707
5708    assert(0.0 <= shoveComponents[0] && shoveComponents[0] <= 1.0);
5709    assert(0.0 <= shoveComponents[1] && shoveComponents[1] <= 1.0);
5710    assert(0.0 <= shoveComponents[2] && shoveComponents[2] <= 1.0);
5711    assert(0.0 <= shoveComponents[3] && shoveComponents[3] <= 1.0);
5712
5713    /* due to limited precision, need to round before shoving */
5714    ((GLushort *)packedPixel)[index] =
5715      ((GLushort)((shoveComponents[0] * 15)+0.5)      ) & 0x000F;
5716    ((GLushort *)packedPixel)[index]|=
5717      ((GLushort)((shoveComponents[1] * 15)+0.5) <<  4) & 0x00F0;
5718    ((GLushort *)packedPixel)[index]|=
5719      ((GLushort)((shoveComponents[2] * 15)+0.5) <<  8) & 0x0F00;
5720    ((GLushort *)packedPixel)[index]|=
5721      ((GLushort)((shoveComponents[3] * 15)+0.5) << 12) & 0xF000;
5722 } /* shove4444rev() */
5723
5724 static void extract5551(int isSwap,const void *packedPixel,
5725                         GLfloat extractComponents[])
5726 {
5727    GLushort ushort;
5728
5729    if (isSwap) {
5730      ushort= __GLU_SWAP_2_BYTES(packedPixel);
5731    }
5732    else {
5733      ushort= *(const GLushort *)packedPixel;
5734    }
5735
5736    /* 11111000,00000000 == 0xf800 */
5737    /* 00000111,11000000 == 0x07c0 */
5738    /* 00000000,00111110 == 0x003e */
5739    /* 00000000,00000001 == 0x0001 */
5740
5741    extractComponents[0]=(float)((ushort & 0xf800) >> 11) / 31.0;/* 31 = 2^5-1*/
5742    extractComponents[1]=(float)((ushort & 0x07c0) >>  6) / 31.0;
5743    extractComponents[2]=(float)((ushort & 0x003e) >>  1) / 31.0;
5744    extractComponents[3]=(float)((ushort & 0x0001)      );
5745 } /* extract5551() */
5746
5747 static void shove5551(const GLfloat shoveComponents[],
5748                       int index,void *packedPixel)
5749 {
5750    /* 11111000,00000000 == 0xf800 */
5751    /* 00000111,11000000 == 0x07c0 */
5752    /* 00000000,00111110 == 0x003e */
5753    /* 00000000,00000001 == 0x0001 */
5754
5755    assert(0.0 <= shoveComponents[0] && shoveComponents[0] <= 1.0);
5756    assert(0.0 <= shoveComponents[1] && shoveComponents[1] <= 1.0);
5757    assert(0.0 <= shoveComponents[2] && shoveComponents[2] <= 1.0);
5758    assert(0.0 <= shoveComponents[3] && shoveComponents[3] <= 1.0);
5759
5760    /* due to limited precision, need to round before shoving */
5761    ((GLushort *)packedPixel)[index]  =
5762      ((GLushort)((shoveComponents[0] * 31)+0.5) << 11) & 0xf800;
5763    ((GLushort *)packedPixel)[index]|=
5764      ((GLushort)((shoveComponents[1] * 31)+0.5) <<  6) & 0x07c0;
5765    ((GLushort *)packedPixel)[index]|=
5766      ((GLushort)((shoveComponents[2] * 31)+0.5) <<  1) & 0x003e;
5767    ((GLushort *)packedPixel)[index]|=
5768      ((GLushort)((shoveComponents[3])+0.5)           ) & 0x0001;
5769 } /* shove5551() */
5770
5771 static void extract1555rev(int isSwap,const void *packedPixel,
5772                            GLfloat extractComponents[])
5773 {
5774    GLushort ushort;
5775
5776    if (isSwap) {
5777      ushort= __GLU_SWAP_2_BYTES(packedPixel);
5778    }
5779    else {
5780      ushort= *(const GLushort *)packedPixel;
5781    }
5782
5783    /* 00000000,00011111 == 0x001F */
5784    /* 00000011,11100000 == 0x03E0 */
5785    /* 01111100,00000000 == 0x7C00 */
5786    /* 10000000,00000000 == 0x8000 */
5787
5788    /* 31 = 2^5-1 */
5789    extractComponents[0]= (float)((ushort & 0x001F)      ) / 31.0;
5790    extractComponents[1]= (float)((ushort & 0x03E0) >>  5) / 31.0;
5791    extractComponents[2]= (float)((ushort & 0x7C00) >> 10) / 31.0;
5792    extractComponents[3]= (float)((ushort & 0x8000) >> 15);
5793 } /* extract1555rev() */
5794
5795 static void shove1555rev(const GLfloat shoveComponents[],
5796                          int index,void *packedPixel)
5797 {
5798    /* 00000000,00011111 == 0x001F */
5799    /* 00000011,11100000 == 0x03E0 */
5800    /* 01111100,00000000 == 0x7C00 */
5801    /* 10000000,00000000 == 0x8000 */
5802
5803    assert(0.0 <= shoveComponents[0] && shoveComponents[0] <= 1.0);
5804    assert(0.0 <= shoveComponents[1] && shoveComponents[1] <= 1.0);
5805    assert(0.0 <= shoveComponents[2] && shoveComponents[2] <= 1.0);
5806    assert(0.0 <= shoveComponents[3] && shoveComponents[3] <= 1.0);
5807
5808    /* due to limited precision, need to round before shoving */
5809    ((GLushort *)packedPixel)[index] =
5810      ((GLushort)((shoveComponents[0] * 31)+0.5)      ) & 0x001F;
5811    ((GLushort *)packedPixel)[index]|=
5812      ((GLushort)((shoveComponents[1] * 31)+0.5) <<  5) & 0x03E0;
5813    ((GLushort *)packedPixel)[index]|=
5814      ((GLushort)((shoveComponents[2] * 31)+0.5) << 10) & 0x7C00;
5815    ((GLushort *)packedPixel)[index]|=
5816      ((GLushort)((shoveComponents[3])+0.5)      << 15) & 0x8000;
5817 } /* shove1555rev() */
5818
5819 static void extract8888(int isSwap,
5820                         const void *packedPixel, GLfloat extractComponents[])
5821 {
5822    GLuint uint;
5823
5824    if (isSwap) {
5825      uint= __GLU_SWAP_4_BYTES(packedPixel);
5826    }
5827    else {
5828      uint= *(const GLuint *)packedPixel;
5829    }
5830
5831    /* 11111111,00000000,00000000,00000000 == 0xff000000 */
5832    /* 00000000,11111111,00000000,00000000 == 0x00ff0000 */
5833    /* 00000000,00000000,11111111,00000000 == 0x0000ff00 */
5834    /* 00000000,00000000,00000000,11111111 == 0x000000ff */
5835
5836    /* 255 = 2^8-1 */
5837    extractComponents[0]= (float)((uint & 0xff000000) >> 24) / 255.0;
5838    extractComponents[1]= (float)((uint & 0x00ff0000) >> 16) / 255.0;
5839    extractComponents[2]= (float)((uint & 0x0000ff00) >>  8) / 255.0;
5840    extractComponents[3]= (float)((uint & 0x000000ff)      ) / 255.0;
5841 } /* extract8888() */
5842
5843 static void shove8888(const GLfloat shoveComponents[],
5844                       int index,void *packedPixel)
5845 {
5846    /* 11111111,00000000,00000000,00000000 == 0xff000000 */
5847    /* 00000000,11111111,00000000,00000000 == 0x00ff0000 */
5848    /* 00000000,00000000,11111111,00000000 == 0x0000ff00 */
5849    /* 00000000,00000000,00000000,11111111 == 0x000000ff */
5850
5851    assert(0.0 <= shoveComponents[0] && shoveComponents[0] <= 1.0);
5852    assert(0.0 <= shoveComponents[1] && shoveComponents[1] <= 1.0);
5853    assert(0.0 <= shoveComponents[2] && shoveComponents[2] <= 1.0);
5854    assert(0.0 <= shoveComponents[3] && shoveComponents[3] <= 1.0);
5855
5856    /* due to limited precision, need to round before shoving */
5857    ((GLuint *)packedPixel)[index] =
5858      ((GLuint)((shoveComponents[0] * 255)+0.5) << 24) & 0xff000000;
5859    ((GLuint *)packedPixel)[index]|=
5860      ((GLuint)((shoveComponents[1] * 255)+0.5) << 16) & 0x00ff0000;
5861    ((GLuint *)packedPixel)[index]|=
5862      ((GLuint)((shoveComponents[2] * 255)+0.5) <<  8) & 0x0000ff00;
5863    ((GLuint *)packedPixel)[index]|=
5864      ((GLuint)((shoveComponents[3] * 255)+0.5)      ) & 0x000000ff;
5865 } /* shove8888() */
5866
5867 static void extract8888rev(int isSwap,
5868                            const void *packedPixel,GLfloat extractComponents[])
5869 {
5870    GLuint uint;
5871
5872    if (isSwap) {
5873      uint= __GLU_SWAP_4_BYTES(packedPixel);
5874    }
5875    else {
5876      uint= *(const GLuint *)packedPixel;
5877    }
5878
5879    /* 00000000,00000000,00000000,11111111 == 0x000000ff */
5880    /* 00000000,00000000,11111111,00000000 == 0x0000ff00 */
5881    /* 00000000,11111111,00000000,00000000 == 0x00ff0000 */
5882    /* 11111111,00000000,00000000,00000000 == 0xff000000 */
5883
5884    /* 255 = 2^8-1 */
5885    extractComponents[0]= (float)((uint & 0x000000FF)      ) / 255.0;
5886    extractComponents[1]= (float)((uint & 0x0000FF00) >>  8) / 255.0;
5887    extractComponents[2]= (float)((uint & 0x00FF0000) >> 16) / 255.0;
5888    extractComponents[3]= (float)((uint & 0xFF000000) >> 24) / 255.0;
5889 } /* extract8888rev() */
5890
5891 static void shove8888rev(const GLfloat shoveComponents[],
5892                          int index,void *packedPixel)
5893 {
5894    /* 00000000,00000000,00000000,11111111 == 0x000000ff */
5895    /* 00000000,00000000,11111111,00000000 == 0x0000ff00 */
5896    /* 00000000,11111111,00000000,00000000 == 0x00ff0000 */
5897    /* 11111111,00000000,00000000,00000000 == 0xff000000 */
5898
5899    assert(0.0 <= shoveComponents[0] && shoveComponents[0] <= 1.0);
5900    assert(0.0 <= shoveComponents[1] && shoveComponents[1] <= 1.0);
5901    assert(0.0 <= shoveComponents[2] && shoveComponents[2] <= 1.0);
5902    assert(0.0 <= shoveComponents[3] && shoveComponents[3] <= 1.0);
5903
5904    /* due to limited precision, need to round before shoving */
5905    ((GLuint *)packedPixel)[index] =
5906      ((GLuint)((shoveComponents[0] * 255)+0.5)      ) & 0x000000FF;
5907    ((GLuint *)packedPixel)[index]|=
5908      ((GLuint)((shoveComponents[1] * 255)+0.5) <<  8) & 0x0000FF00;
5909    ((GLuint *)packedPixel)[index]|=
5910      ((GLuint)((shoveComponents[2] * 255)+0.5) << 16) & 0x00FF0000;
5911    ((GLuint *)packedPixel)[index]|=
5912      ((GLuint)((shoveComponents[3] * 255)+0.5) << 24) & 0xFF000000;
5913 } /* shove8888rev() */
5914
5915 static void extract1010102(int isSwap,
5916                            const void *packedPixel,GLfloat extractComponents[])
5917 {
5918    GLuint uint;
5919
5920    if (isSwap) {
5921      uint= __GLU_SWAP_4_BYTES(packedPixel);
5922    }
5923    else {
5924      uint= *(const GLuint *)packedPixel;
5925    }
5926
5927    /* 11111111,11000000,00000000,00000000 == 0xffc00000 */
5928    /* 00000000,00111111,11110000,00000000 == 0x003ff000 */
5929    /* 00000000,00000000,00001111,11111100 == 0x00000ffc */
5930    /* 00000000,00000000,00000000,00000011 == 0x00000003 */
5931
5932    /* 1023 = 2^10-1 */
5933    extractComponents[0]= (float)((uint & 0xffc00000) >> 22) / 1023.0;
5934    extractComponents[1]= (float)((uint & 0x003ff000) >> 12) / 1023.0;
5935    extractComponents[2]= (float)((uint & 0x00000ffc) >>  2) / 1023.0;
5936    extractComponents[3]= (float)((uint & 0x00000003)      ) / 3.0;
5937 } /* extract1010102() */
5938
5939 static void shove1010102(const GLfloat shoveComponents[],
5940                          int index,void *packedPixel)
5941 {
5942    /* 11111111,11000000,00000000,00000000 == 0xffc00000 */
5943    /* 00000000,00111111,11110000,00000000 == 0x003ff000 */
5944    /* 00000000,00000000,00001111,11111100 == 0x00000ffc */
5945    /* 00000000,00000000,00000000,00000011 == 0x00000003 */
5946
5947    assert(0.0 <= shoveComponents[0] && shoveComponents[0] <= 1.0);
5948    assert(0.0 <= shoveComponents[1] && shoveComponents[1] <= 1.0);
5949    assert(0.0 <= shoveComponents[2] && shoveComponents[2] <= 1.0);
5950    assert(0.0 <= shoveComponents[3] && shoveComponents[3] <= 1.0);
5951
5952    /* due to limited precision, need to round before shoving */
5953    ((GLuint *)packedPixel)[index] =
5954      ((GLuint)((shoveComponents[0] * 1023)+0.5) << 22) & 0xffc00000;
5955    ((GLuint *)packedPixel)[index]|=
5956      ((GLuint)((shoveComponents[1] * 1023)+0.5) << 12) & 0x003ff000;
5957    ((GLuint *)packedPixel)[index]|=
5958      ((GLuint)((shoveComponents[2] * 1023)+0.5) <<  2) & 0x00000ffc;
5959    ((GLuint *)packedPixel)[index]|=
5960      ((GLuint)((shoveComponents[3] * 3)+0.5)         ) & 0x00000003;
5961 } /* shove1010102() */
5962
5963 static void extract2101010rev(int isSwap,
5964                               const void *packedPixel,
5965                               GLfloat extractComponents[])
5966 {
5967    GLuint uint;
5968
5969    if (isSwap) {
5970      uint= __GLU_SWAP_4_BYTES(packedPixel);
5971    }
5972    else {
5973      uint= *(const GLuint *)packedPixel;
5974    }
5975
5976    /* 00000000,00000000,00000011,11111111 == 0x000003FF */
5977    /* 00000000,00001111,11111100,00000000 == 0x000FFC00 */
5978    /* 00111111,11110000,00000000,00000000 == 0x3FF00000 */
5979    /* 11000000,00000000,00000000,00000000 == 0xC0000000 */
5980
5981    /* 1023 = 2^10-1 */
5982    extractComponents[0]= (float)((uint & 0x000003FF)      ) / 1023.0;
5983    extractComponents[1]= (float)((uint & 0x000FFC00) >> 10) / 1023.0;
5984    extractComponents[2]= (float)((uint & 0x3FF00000) >> 20) / 1023.0;
5985    extractComponents[3]= (float)((uint & 0xC0000000) >> 30) / 3.0;
5986    /* 3 = 2^2-1 */
5987 } /* extract2101010rev() */
5988
5989 static void shove2101010rev(const GLfloat shoveComponents[],
5990                             int index,void *packedPixel)
5991 {
5992    /* 00000000,00000000,00000011,11111111 == 0x000003FF */
5993    /* 00000000,00001111,11111100,00000000 == 0x000FFC00 */
5994    /* 00111111,11110000,00000000,00000000 == 0x3FF00000 */
5995    /* 11000000,00000000,00000000,00000000 == 0xC0000000 */
5996
5997    assert(0.0 <= shoveComponents[0] && shoveComponents[0] <= 1.0);
5998    assert(0.0 <= shoveComponents[1] && shoveComponents[1] <= 1.0);
5999    assert(0.0 <= shoveComponents[2] && shoveComponents[2] <= 1.0);
6000    assert(0.0 <= shoveComponents[3] && shoveComponents[3] <= 1.0);
6001
6002    /* due to limited precision, need to round before shoving */
6003    ((GLuint *)packedPixel)[index] =
6004      ((GLuint)((shoveComponents[0] * 1023)+0.5)      ) & 0x000003FF;
6005    ((GLuint *)packedPixel)[index]|=
6006      ((GLuint)((shoveComponents[1] * 1023)+0.5) << 10) & 0x000FFC00;
6007    ((GLuint *)packedPixel)[index]|=
6008      ((GLuint)((shoveComponents[2] * 1023)+0.5) << 20) & 0x3FF00000;
6009    ((GLuint *)packedPixel)[index]|=
6010      ((GLuint)((shoveComponents[3] * 3)+0.5)    << 30) & 0xC0000000;
6011 } /* shove2101010rev() */
6012
6013 static void scaleInternalPackedPixel(int components,
6014                                      void (*extractPackedPixel)
6015                                      (int, const void *,GLfloat []),
6016                                      void (*shovePackedPixel)
6017                                      (const GLfloat [], int, void *),
6018                                      GLint widthIn,GLint heightIn,
6019                                      const void *dataIn,
6020                                      GLint widthOut,GLint heightOut,
6021                                      void *dataOut,
6022                                      GLint pixelSizeInBytes,
6023                                      GLint rowSizeInBytes,GLint isSwap)
6024 {
6025     float convx;
6026     float convy;
6027     float percent;
6028
6029     /* Max components in a format is 4, so... */
6030     float totals[4];
6031     float extractTotals[4], extractMoreTotals[4], shoveTotals[4];
6032
6033     float area;
6034     int i,j,k,xindex;
6035
6036     const char *temp, *temp0;
6037     int outindex;
6038
6039     int lowx_int, highx_int, lowy_int, highy_int;
6040     float x_percent, y_percent;
6041     float lowx_float, highx_float, lowy_float, highy_float;
6042     float convy_float, convx_float;
6043     int convy_int, convx_int;
6044     int l, m;
6045     const char *left, *right;
6046
6047     if (widthIn == widthOut*2 && heightIn == heightOut*2) {
6048         halveImagePackedPixel(components,extractPackedPixel,shovePackedPixel,
6049                               widthIn, heightIn, dataIn, dataOut,
6050                               pixelSizeInBytes,rowSizeInBytes,isSwap);
6051         return;
6052     }
6053     convy = (float) heightIn/heightOut;
6054     convx = (float) widthIn/widthOut;
6055     convy_int = floor(convy);
6056     convy_float = convy - convy_int;
6057     convx_int = floor(convx);
6058     convx_float = convx - convx_int;
6059
6060     area = convx * convy;
6061
6062     lowy_int = 0;
6063     lowy_float = 0;
6064     highy_int = convy_int;
6065     highy_float = convy_float;
6066
6067     for (i = 0; i < heightOut; i++) {
6068         lowx_int = 0;
6069         lowx_float = 0;
6070         highx_int = convx_int;
6071         highx_float = convx_float;
6072
6073         for (j = 0; j < widthOut; j++) {
6074             /*
6075             ** Ok, now apply box filter to box that goes from (lowx, lowy)
6076             ** to (highx, highy) on input data into this pixel on output
6077             ** data.
6078             */
6079             totals[0] = totals[1] = totals[2] = totals[3] = 0.0;
6080
6081             /* calculate the value for pixels in the 1st row */
6082             xindex = lowx_int*pixelSizeInBytes;
6083             if((highy_int>lowy_int) && (highx_int>lowx_int)) {
6084
6085                 y_percent = 1-lowy_float;
6086                 temp = (const char *)dataIn + xindex + lowy_int * rowSizeInBytes;
6087                 percent = y_percent * (1-lowx_float);
6088 #if 0
6089                 for (k = 0, temp_index = temp; k < components;
6090                      k++, temp_index += element_size) {
6091                     if (myswap_bytes) {
6092                         totals[k] += __GLU_SWAP_2_BYTES(temp_index) * percent;
6093                     } else {
6094                         totals[k] += *(const GLushort*)temp_index * percent;
6095                     }
6096                 }
6097 #else
6098                 (*extractPackedPixel)(isSwap,temp,extractTotals);
6099                 for (k = 0; k < components; k++) {
6100                    totals[k]+= extractTotals[k] * percent;
6101                 }
6102 #endif
6103                 left = temp;
6104                 for(l = lowx_int+1; l < highx_int; l++) {
6105                     temp += pixelSizeInBytes;
6106 #if 0
6107                     for (k = 0, temp_index = temp; k < components;
6108                          k++, temp_index += element_size) {
6109                         if (myswap_bytes) {
6110                             totals[k] +=
6111                                  __GLU_SWAP_2_BYTES(temp_index) * y_percent;
6112                         } else {
6113                             totals[k] += *(const GLushort*)temp_index * y_percent;
6114                         }
6115                     }
6116 #else
6117                     (*extractPackedPixel)(isSwap,temp,extractTotals);
6118                     for (k = 0; k < components; k++) {
6119                        totals[k]+= extractTotals[k] * y_percent;
6120                     }
6121 #endif
6122                 }
6123                 temp += pixelSizeInBytes;
6124                 right = temp;
6125                 percent = y_percent * highx_float;
6126 #if 0
6127                 for (k = 0, temp_index = temp; k < components;
6128                      k++, temp_index += element_size) {
6129                     if (myswap_bytes) {
6130                         totals[k] += __GLU_SWAP_2_BYTES(temp_index) * percent;
6131                     } else {
6132                         totals[k] += *(const GLushort*)temp_index * percent;
6133                     }
6134                 }
6135 #else
6136                 (*extractPackedPixel)(isSwap,temp,extractTotals);
6137                 for (k = 0; k < components; k++) {
6138                    totals[k]+= extractTotals[k] * percent;
6139                 }
6140 #endif
6141
6142                 /* calculate the value for pixels in the last row */
6143                 
6144                 y_percent = highy_float;
6145                 percent = y_percent * (1-lowx_float);
6146                 temp = (const char *)dataIn + xindex + highy_int * rowSizeInBytes;
6147 #if 0
6148                 for (k = 0, temp_index = temp; k < components;
6149                      k++, temp_index += element_size) {
6150                     if (myswap_bytes) {
6151                         totals[k] += __GLU_SWAP_2_BYTES(temp_index) * percent;
6152                     } else {
6153                         totals[k] += *(const GLushort*)temp_index * percent;
6154                     }
6155                 }
6156 #else
6157                 (*extractPackedPixel)(isSwap,temp,extractTotals);
6158                 for (k = 0; k < components; k++) {
6159                    totals[k]+= extractTotals[k] * percent;
6160                 }
6161 #endif
6162                 for(l = lowx_int+1; l < highx_int; l++) {
6163                     temp += pixelSizeInBytes;
6164 #if 0
6165                     for (k = 0, temp_index = temp; k < components;
6166                          k++, temp_index += element_size) {
6167                         if (myswap_bytes) {
6168                             totals[k] +=
6169                                  __GLU_SWAP_2_BYTES(temp_index) * y_percent;
6170                         } else {
6171                             totals[k] += *(const GLushort*)temp_index * y_percent;
6172                         }
6173                     }
6174 #else
6175                     (*extractPackedPixel)(isSwap,temp,extractTotals);
6176                     for (k = 0; k < components; k++) {
6177                        totals[k]+= extractTotals[k] * y_percent;
6178                     }
6179 #endif
6180
6181                 }
6182                 temp += pixelSizeInBytes;
6183                 percent = y_percent * highx_float;
6184 #if 0
6185                 for (k = 0, temp_index = temp; k < components;
6186                      k++, temp_index += element_size) {
6187                     if (myswap_bytes) {
6188                         totals[k] += __GLU_SWAP_2_BYTES(temp_index) * percent;
6189                     } else {
6190                         totals[k] += *(const GLushort*)temp_index * percent;
6191                     }
6192                 }
6193 #else
6194                 (*extractPackedPixel)(isSwap,temp,extractTotals);
6195                 for (k = 0; k < components; k++) {
6196                    totals[k]+= extractTotals[k] * percent;
6197                 }
6198 #endif
6199
6200                 /* calculate the value for pixels in the 1st and last column */
6201                 for(m = lowy_int+1; m < highy_int; m++) {
6202                     left += rowSizeInBytes;
6203                     right += rowSizeInBytes;
6204 #if 0
6205                     for (k = 0; k < components;
6206                          k++, left += element_size, right += element_size) {
6207                         if (myswap_bytes) {
6208                             totals[k] +=
6209                                 __GLU_SWAP_2_BYTES(left) * (1-lowx_float) +
6210                                 __GLU_SWAP_2_BYTES(right) * highx_float;
6211                         } else {
6212                             totals[k] += *(const GLushort*)left * (1-lowx_float)
6213                                        + *(const GLushort*)right * highx_float;
6214                         }
6215                     }
6216 #else
6217                     (*extractPackedPixel)(isSwap,left,extractTotals);
6218                     (*extractPackedPixel)(isSwap,right,extractMoreTotals);
6219                     for (k = 0; k < components; k++) {
6220                        totals[k]+= (extractTotals[k]*(1-lowx_float) +
6221                                    extractMoreTotals[k]*highx_float);
6222                     }
6223 #endif
6224                 }
6225             } else if (highy_int > lowy_int) {
6226                 x_percent = highx_float - lowx_float;
6227                 percent = (1-lowy_float)*x_percent;
6228                 temp = (const char *)dataIn + xindex + lowy_int*rowSizeInBytes;
6229 #if 0
6230                 for (k = 0, temp_index = temp; k < components;
6231                      k++, temp_index += element_size) {
6232                     if (myswap_bytes) {
6233                         totals[k] += __GLU_SWAP_2_BYTES(temp_index) * percent;
6234                     } else {
6235                         totals[k] += *(const GLushort*)temp_index * percent;
6236                     }
6237                 }
6238 #else
6239                 (*extractPackedPixel)(isSwap,temp,extractTotals);
6240                 for (k = 0; k < components; k++) {
6241                    totals[k]+= extractTotals[k] * percent;
6242                 }
6243 #endif
6244                 for(m = lowy_int+1; m < highy_int; m++) {
6245                     temp += rowSizeInBytes;
6246 #if 0
6247                     for (k = 0, temp_index = temp; k < components;
6248                          k++, temp_index += element_size) {
6249                         if (myswap_bytes) {
6250                             totals[k] +=
6251                                 __GLU_SWAP_2_BYTES(temp_index) * x_percent;
6252                         } else {
6253                             totals[k] += *(const GLushort*)temp_index * x_percent;
6254                         }
6255                     }
6256 #else
6257                     (*extractPackedPixel)(isSwap,temp,extractTotals);
6258                     for (k = 0; k < components; k++) {
6259                        totals[k]+= extractTotals[k] * x_percent;
6260                     }
6261 #endif
6262                 }
6263                 percent = x_percent * highy_float;
6264                 temp += rowSizeInBytes;
6265 #if 0
6266                 for (k = 0, temp_index = temp; k < components;
6267                      k++, temp_index += element_size) {
6268                     if (myswap_bytes) {
6269                         totals[k] += __GLU_SWAP_2_BYTES(temp_index) * percent;
6270                     } else {
6271                         totals[k] += *(const GLushort*)temp_index * percent;
6272                     }
6273                 }
6274 #else
6275                 (*extractPackedPixel)(isSwap,temp,extractTotals);
6276                 for (k = 0; k < components; k++) {
6277                    totals[k]+= extractTotals[k] * percent;
6278                 }
6279 #endif
6280             } else if (highx_int > lowx_int) {
6281                 y_percent = highy_float - lowy_float;
6282                 percent = (1-lowx_float)*y_percent;
6283                 temp = (const char *)dataIn + xindex + lowy_int*rowSizeInBytes;
6284 #if 0
6285                 for (k = 0, temp_index = temp; k < components;
6286                      k++, temp_index += element_size) {
6287                     if (myswap_bytes) {
6288                         totals[k] += __GLU_SWAP_2_BYTES(temp_index) * percent;
6289                     } else {
6290                         totals[k] += *(const GLushort*)temp_index * percent;
6291                     }
6292                 }
6293 #else
6294                 (*extractPackedPixel)(isSwap,temp,extractTotals);
6295                 for (k = 0; k < components; k++) {
6296                    totals[k]+= extractTotals[k] * percent;
6297                 }
6298 #endif
6299                 for (l = lowx_int+1; l < highx_int; l++) {
6300                     temp += pixelSizeInBytes;
6301 #if 0
6302                     for (k = 0, temp_index = temp; k < components;
6303                          k++, temp_index += element_size) {
6304                         if (myswap_bytes) {
6305                             totals[k] +=
6306                                 __GLU_SWAP_2_BYTES(temp_index) * y_percent;
6307                         } else {
6308                             totals[k] += *(const GLushort*)temp_index * y_percent;
6309                         }
6310                     }
6311 #else
6312                 (*extractPackedPixel)(isSwap,temp,extractTotals);
6313                 for (k = 0; k < components; k++) {
6314                    totals[k]+= extractTotals[k] * y_percent;
6315                 }
6316 #endif
6317                 }
6318                 temp += pixelSizeInBytes;
6319                 percent = y_percent * highx_float;
6320 #if 0
6321                 for (k = 0, temp_index = temp; k < components;
6322                      k++, temp_index += element_size) {
6323                     if (myswap_bytes) {
6324                         totals[k] += __GLU_SWAP_2_BYTES(temp_index) * percent;
6325                     } else {
6326                         totals[k] += *(const GLushort*)temp_index * percent;
6327                     }
6328                 }
6329 #else
6330                 (*extractPackedPixel)(isSwap,temp,extractTotals);
6331                 for (k = 0; k < components; k++) {
6332                    totals[k]+= extractTotals[k] * percent;
6333                 }
6334 #endif
6335             } else {
6336                 percent = (highy_float-lowy_float)*(highx_float-lowx_float);
6337                 temp = (const char *)dataIn + xindex + lowy_int * rowSizeInBytes;
6338 #if 0
6339                 for (k = 0, temp_index = temp; k < components;
6340                      k++, temp_index += element_size) {
6341                     if (myswap_bytes) {
6342                         totals[k] += __GLU_SWAP_2_BYTES(temp_index) * percent;
6343                     } else {
6344                         totals[k] += *(const GLushort*)temp_index * percent;
6345                     }
6346                 }
6347 #else
6348                 (*extractPackedPixel)(isSwap,temp,extractTotals);
6349                 for (k = 0; k < components; k++) {
6350                    totals[k]+= extractTotals[k] * percent;
6351                 }
6352 #endif
6353             }
6354
6355             /* this is for the pixels in the body */
6356             temp0 = (const char *)dataIn + xindex + pixelSizeInBytes + (lowy_int+1)*rowSizeInBytes;
6357             for (m = lowy_int+1; m < highy_int; m++) {
6358                 temp = temp0;
6359                 for(l = lowx_int+1; l < highx_int; l++) {
6360 #if 0
6361                     for (k = 0, temp_index = temp; k < components;
6362                          k++, temp_index += element_size) {
6363                         if (myswap_bytes) {
6364                             totals[k] += __GLU_SWAP_2_BYTES(temp_index);
6365                         } else {
6366                             totals[k] += *(const GLushort*)temp_index;
6367                         }
6368                     }
6369 #else
6370                     (*extractPackedPixel)(isSwap,temp,extractTotals);
6371                     for (k = 0; k < components; k++) {
6372                        totals[k]+= extractTotals[k];
6373                     }
6374 #endif
6375                     temp += pixelSizeInBytes;
6376                 }
6377                 temp0 += rowSizeInBytes;
6378             }
6379
6380             outindex = (j + (i * widthOut)); /* * (components == 1) */
6381 #if 0
6382             for (k = 0; k < components; k++) {
6383                 dataout[outindex + k] = totals[k]/area;
6384                 /*printf("totals[%d] = %f\n", k, totals[k]);*/
6385             }
6386 #else
6387             for (k = 0; k < components; k++) {
6388                 shoveTotals[k]= totals[k]/area;
6389             }
6390             (*shovePackedPixel)(shoveTotals,outindex,(void *)dataOut);
6391 #endif
6392             lowx_int = highx_int;
6393             lowx_float = highx_float;
6394             highx_int += convx_int;
6395             highx_float += convx_float;
6396             if(highx_float > 1) {
6397                 highx_float -= 1.0;
6398                 highx_int++;
6399             }
6400         }
6401         lowy_int = highy_int;
6402         lowy_float = highy_float;
6403         highy_int += convy_int;
6404         highy_float += convy_float;
6405         if(highy_float > 1) {
6406             highy_float -= 1.0;
6407             highy_int++;
6408         }
6409     }
6410
6411     assert(outindex == (widthOut*heightOut - 1));
6412 } /* scaleInternalPackedPixel() */
6413
6414 /* rowSizeInBytes is at least the width (in bytes) due to padding on
6415  *  inputs; not always equal. Output NEVER has row padding.
6416  */
6417 static void halveImagePackedPixel(int components,
6418                                   void (*extractPackedPixel)
6419                                   (int, const void *,GLfloat []),
6420                                   void (*shovePackedPixel)
6421                                   (const GLfloat [],int, void *),
6422                                   GLint width, GLint height,
6423                                   const void *dataIn, void *dataOut,
6424                                   GLint pixelSizeInBytes,
6425                                   GLint rowSizeInBytes, GLint isSwap)
6426 {
6427    /* handle case where there is only 1 column/row */
6428    if (width == 1 || height == 1) {
6429       assert(!(width == 1 && height == 1)); /* can't be 1x1 */
6430       halve1DimagePackedPixel(components,extractPackedPixel,shovePackedPixel,
6431                               width,height,dataIn,dataOut,pixelSizeInBytes,
6432                               rowSizeInBytes,isSwap);
6433       return;
6434    }
6435
6436    {
6437       int ii, jj;
6438
6439       int halfWidth= width / 2;
6440       int halfHeight= height / 2;
6441       const char *src= (const char *) dataIn;
6442       int padBytes= rowSizeInBytes - (width*pixelSizeInBytes);
6443       int outIndex= 0;
6444
6445       for (ii= 0; ii< halfHeight; ii++) {
6446          for (jj= 0; jj< halfWidth; jj++) {
6447 #define BOX4 4
6448             float totals[4];    /* 4 is maximum components */
6449             float extractTotals[BOX4][4]; /* 4 is maximum components */
6450             int cc;
6451
6452             (*extractPackedPixel)(isSwap,src,
6453                                   &extractTotals[0][0]);
6454             (*extractPackedPixel)(isSwap,(src+pixelSizeInBytes),
6455                                   &extractTotals[1][0]);
6456             (*extractPackedPixel)(isSwap,(src+rowSizeInBytes),
6457                                   &extractTotals[2][0]);
6458             (*extractPackedPixel)(isSwap,
6459                                   (src+rowSizeInBytes+pixelSizeInBytes),
6460                                   &extractTotals[3][0]);
6461             for (cc = 0; cc < components; cc++) {
6462                int kk;
6463
6464                /* grab 4 pixels to average */
6465                totals[cc]= 0.0;
6466                /* totals[RED]= extractTotals[0][RED]+extractTotals[1][RED]+
6467                 *              extractTotals[2][RED]+extractTotals[3][RED];
6468                 * totals[RED]/= 4.0;
6469                 */
6470                for (kk = 0; kk < BOX4; kk++) {
6471                   totals[cc]+= extractTotals[kk][cc];
6472                }
6473                totals[cc]/= (float)BOX4;
6474             }
6475             (*shovePackedPixel)(totals,outIndex,dataOut);
6476
6477             outIndex++;
6478             /* skip over to next square of 4 */
6479             src+= pixelSizeInBytes + pixelSizeInBytes;
6480          }
6481          /* skip past pad bytes, if any, to get to next row */
6482          src+= padBytes;
6483
6484          /* src is at beginning of a row here, but it's the second row of
6485           * the square block of 4 pixels that we just worked on so we
6486           * need to go one more row.
6487           * i.e.,
6488           *                   OO...
6489           *           here -->OO...
6490           *       but want -->OO...
6491           *                   OO...
6492           *                   ...
6493           */
6494          src+= rowSizeInBytes;
6495       }
6496
6497       /* both pointers must reach one byte after the end */
6498       assert(src == &((const char *)dataIn)[rowSizeInBytes*height]);
6499       assert(outIndex == halfWidth * halfHeight);
6500    }
6501 } /* halveImagePackedPixel() */
6502
6503 static void halve1DimagePackedPixel(int components,
6504                                     void (*extractPackedPixel)
6505                                     (int, const void *,GLfloat []),
6506                                     void (*shovePackedPixel)
6507                                     (const GLfloat [],int, void *),
6508                                     GLint width, GLint height,
6509                                     const void *dataIn, void *dataOut,
6510                                     GLint pixelSizeInBytes,
6511                                     GLint rowSizeInBytes, GLint isSwap)
6512 {
6513    int halfWidth= width / 2;
6514    int halfHeight= height / 2;
6515    const char *src= (const char *) dataIn;
6516    int jj;
6517
6518    assert(width == 1 || height == 1); /* must be 1D */
6519    assert(width != height);     /* can't be square */
6520
6521    if (height == 1) {   /* 1 row */
6522       int outIndex= 0;
6523
6524       assert(width != 1);       /* widthxheight can't be 1x1 */
6525       halfHeight= 1;
6526
6527       /* one horizontal row with possible pad bytes */
6528
6529       for (jj= 0; jj< halfWidth; jj++) {
6530 #define BOX2 2
6531          float totals[4];       /* 4 is maximum components */
6532          float extractTotals[BOX2][4]; /* 4 is maximum components */
6533          int cc;
6534
6535          /* average two at a time, instead of four */
6536          (*extractPackedPixel)(isSwap,src,
6537                                &extractTotals[0][0]);
6538          (*extractPackedPixel)(isSwap,(src+pixelSizeInBytes),
6539                                &extractTotals[1][0]);                   
6540          for (cc = 0; cc < components; cc++) {
6541             int kk;
6542
6543             /* grab 2 pixels to average */
6544             totals[cc]= 0.0;
6545             /* totals[RED]= extractTotals[0][RED]+extractTotals[1][RED];
6546              * totals[RED]/= 2.0;
6547              */
6548             for (kk = 0; kk < BOX2; kk++) {
6549                totals[cc]+= extractTotals[kk][cc];
6550             }
6551             totals[cc]/= (float)BOX2;
6552          }
6553          (*shovePackedPixel)(totals,outIndex,dataOut);
6554
6555          outIndex++;
6556          /* skip over to next group of 2 */
6557          src+= pixelSizeInBytes + pixelSizeInBytes;
6558       }
6559
6560       {
6561          int padBytes= rowSizeInBytes - (width*pixelSizeInBytes);
6562          src+= padBytes;        /* for assertion only */
6563       }
6564       assert(src == &((const char *)dataIn)[rowSizeInBytes]);
6565       assert(outIndex == halfWidth * halfHeight);
6566    }
6567    else if (width == 1) { /* 1 column */
6568       int outIndex= 0;
6569
6570       assert(height != 1);      /* widthxheight can't be 1x1 */
6571       halfWidth= 1;
6572       /* one vertical column with possible pad bytes per row */
6573       /* average two at a time */
6574
6575       for (jj= 0; jj< halfHeight; jj++) {
6576 #define BOX2 2
6577          float totals[4];       /* 4 is maximum components */
6578          float extractTotals[BOX2][4]; /* 4 is maximum components */
6579          int cc;
6580
6581          /* average two at a time, instead of four */
6582          (*extractPackedPixel)(isSwap,src,
6583                                &extractTotals[0][0]);
6584          (*extractPackedPixel)(isSwap,(src+rowSizeInBytes),
6585                                &extractTotals[1][0]);                   
6586          for (cc = 0; cc < components; cc++) {
6587             int kk;
6588
6589             /* grab 2 pixels to average */
6590             totals[cc]= 0.0;
6591             /* totals[RED]= extractTotals[0][RED]+extractTotals[1][RED];
6592              * totals[RED]/= 2.0;
6593              */
6594             for (kk = 0; kk < BOX2; kk++) {
6595                totals[cc]+= extractTotals[kk][cc];
6596             }
6597             totals[cc]/= (float)BOX2;
6598          }
6599          (*shovePackedPixel)(totals,outIndex,dataOut);
6600
6601          outIndex++;
6602          src+= rowSizeInBytes + rowSizeInBytes; /* go to row after next */
6603       }
6604
6605       assert(src == &((const char *)dataIn)[rowSizeInBytes*height]);
6606       assert(outIndex == halfWidth * halfHeight);
6607    }
6608 } /* halve1DimagePackedPixel() */
6609
6610 /*===========================================================================*/
6611
6612 #ifdef RESOLVE_3D_TEXTURE_SUPPORT
6613 /*
6614  * This section ensures that GLU 1.3 will load and run on
6615  * a GL 1.1 implementation. It dynamically resolves the
6616  * call to glTexImage3D() which might not be available.
6617  * Or is it might be supported as an extension.
6618  * Contributed by Gerk Huisma <gerk@five-d.demon.nl>.
6619  */
6620
6621 typedef void (GLAPIENTRY *TexImage3Dproc)( GLenum target, GLint level,
6622                                                  GLenum internalFormat,
6623                                                  GLsizei width, GLsizei height,
6624                                                  GLsizei depth, GLint border,
6625                                                  GLenum format, GLenum type,
6626                                                  const GLvoid *pixels );
6627
6628 static TexImage3Dproc pTexImage3D = 0;
6629
6630 #if !defined(_WIN32) && !defined(__WIN32__)
6631 #  include <dlfcn.h>
6632 #  include <sys/types.h>
6633 #else
6634   WINGDIAPI PROC  WINAPI wglGetProcAddress(LPCSTR);
6635 #endif
6636
6637 static void gluTexImage3D( GLenum target, GLint level,
6638                            GLenum internalFormat,
6639                            GLsizei width, GLsizei height,
6640                            GLsizei depth, GLint border,
6641                            GLenum format, GLenum type,
6642                            const GLvoid *pixels )
6643 {
6644    if (!pTexImage3D) {
6645 #if defined(_WIN32) || defined(__WIN32__)
6646       pTexImage3D = (TexImage3Dproc) wglGetProcAddress("glTexImage3D");
6647       if (!pTexImage3D)
6648          pTexImage3D = (TexImage3Dproc) wglGetProcAddress("glTexImage3DEXT");
6649 #else
6650       void *libHandle = dlopen("libgl.so", RTLD_LAZY);
6651       pTexImage3D = TexImage3Dproc) dlsym(libHandle, "glTexImage3D" );
6652       if (!pTexImage3D)
6653          pTexImage3D = (TexImage3Dproc) dlsym(libHandle,"glTexImage3DEXT");
6654       dlclose(libHandle);
6655 #endif
6656    }
6657
6658    /* Now call glTexImage3D */
6659    if (pTexImage3D)
6660       pTexImage3D(target, level, internalFormat, width, height,
6661                   depth, border, format, type, pixels);
6662 }
6663
6664 #else
6665
6666 /* Only bind to a GL 1.2 implementation: */
6667 #define gluTexImage3D glTexImage3D
6668
6669 #endif
6670
6671 static GLint imageSize3D(GLint width, GLint height, GLint depth,
6672                          GLenum format, GLenum type)
6673 {
6674     int components= elements_per_group(format,type);
6675     int bytes_per_row=  bytes_per_element(type) * width;
6676
6677 assert(width > 0 && height > 0 && depth > 0);
6678 assert(type != GL_BITMAP);
6679
6680     return bytes_per_row * height * depth * components;
6681 } /* imageSize3D() */
6682
6683 static void fillImage3D(const PixelStorageModes *psm,
6684                         GLint width, GLint height, GLint depth, GLenum format,
6685                         GLenum type, GLboolean indexFormat,
6686                         const void *userImage, GLushort *newImage)
6687 {
6688    int myswapBytes;
6689    int components;
6690    int groupsPerLine;
6691    int elementSize;
6692    int groupSize;
6693    int rowSize;
6694    int padding;
6695    int elementsPerLine;
6696    int rowsPerImage;
6697    int imageSize;
6698    const GLubyte *start, *rowStart, *iter;
6699    GLushort *iter2;
6700    int ww, hh, dd, k;
6701
6702    myswapBytes= psm->unpack_swap_bytes;
6703    components= elements_per_group(format,type);
6704    if (psm->unpack_row_length > 0) {
6705       groupsPerLine= psm->unpack_row_length;
6706    }
6707    else {
6708       groupsPerLine= width;
6709    }
6710    elementSize= bytes_per_element(type);
6711    groupSize= elementSize * components;
6712    if (elementSize == 1) myswapBytes= 0;
6713
6714    /* 3dstuff begin */
6715    if (psm->unpack_image_height > 0) {
6716       rowsPerImage= psm->unpack_image_height;
6717    }
6718    else {
6719       rowsPerImage= height;
6720    }
6721    /* 3dstuff end */
6722
6723    rowSize= groupsPerLine * groupSize;
6724    padding= rowSize % psm->unpack_alignment;
6725    if (padding) {
6726       rowSize+= psm->unpack_alignment - padding;
6727    }
6728
6729    imageSize= rowsPerImage * rowSize; /* 3dstuff */
6730
6731    start= (const GLubyte *)userImage + psm->unpack_skip_rows * rowSize +
6732                                  psm->unpack_skip_pixels * groupSize +
6733                                  /*3dstuff*/
6734                                  psm->unpack_skip_images * imageSize;
6735    elementsPerLine = width * components;
6736
6737    iter2= newImage;
6738    for (dd= 0; dd < depth; dd++) {
6739       rowStart= start;
6740
6741       for (hh= 0; hh < height; hh++) {
6742          iter= rowStart;
6743
6744          for (ww= 0; ww < elementsPerLine; ww++) {
6745             Type_Widget widget;
6746             float extractComponents[4];
6747
6748             switch(type) {
6749             case GL_UNSIGNED_BYTE:
6750               if (indexFormat) {
6751                   *iter2++ = *iter;
6752               } else {
6753                   *iter2++ = (*iter) * 257;
6754               }
6755               break;
6756             case GL_BYTE:
6757               if (indexFormat) {
6758                   *iter2++ = *((const GLbyte *) iter);
6759               } else {
6760                   /* rough approx */
6761                   *iter2++ = (*((const GLbyte *) iter)) * 516;
6762               }
6763               break;
6764             case GL_UNSIGNED_BYTE_3_3_2:
6765               extract332(0,iter,extractComponents);
6766               for (k = 0; k < 3; k++) {
6767                 *iter2++ = (GLushort)(extractComponents[k]*65535);
6768               }
6769               break;
6770             case GL_UNSIGNED_BYTE_2_3_3_REV:
6771               extract233rev(0,iter,extractComponents);
6772               for (k = 0; k < 3; k++) {
6773                 *iter2++ = (GLushort)(extractComponents[k]*65535);
6774               }
6775               break;
6776             case GL_UNSIGNED_SHORT_5_6_5:                               
6777               extract565(myswapBytes,iter,extractComponents);
6778               for (k = 0; k < 3; k++) {
6779                 *iter2++ = (GLushort)(extractComponents[k]*65535);
6780               }
6781               break;
6782             case GL_UNSIGNED_SHORT_5_6_5_REV:                           
6783               extract565rev(myswapBytes,iter,extractComponents);
6784               for (k = 0; k < 3; k++) {
6785                 *iter2++ = (GLushort)(extractComponents[k]*65535);
6786               }
6787               break;
6788             case GL_UNSIGNED_SHORT_4_4_4_4:             
6789               extract4444(myswapBytes,iter,extractComponents);
6790               for (k = 0; k < 4; k++) {
6791                 *iter2++ = (GLushort)(extractComponents[k]*65535);
6792               }
6793               break;
6794             case GL_UNSIGNED_SHORT_4_4_4_4_REV:         
6795               extract4444rev(myswapBytes,iter,extractComponents);
6796               for (k = 0; k < 4; k++) {
6797                 *iter2++ = (GLushort)(extractComponents[k]*65535);
6798               }
6799               break;
6800             case GL_UNSIGNED_SHORT_5_5_5_1:             
6801               extract5551(myswapBytes,iter,extractComponents);
6802               for (k = 0; k < 4; k++) {
6803                 *iter2++ = (GLushort)(extractComponents[k]*65535);
6804               }
6805               break;
6806             case GL_UNSIGNED_SHORT_1_5_5_5_REV:
6807               extract1555rev(myswapBytes,iter,extractComponents);
6808               for (k = 0; k < 4; k++) {
6809                 *iter2++ = (GLushort)(extractComponents[k]*65535);
6810               }
6811               break;
6812             case GL_UNSIGNED_SHORT:
6813             case GL_SHORT:
6814               if (myswapBytes) {
6815                   widget.ub[0] = iter[1];
6816                   widget.ub[1] = iter[0];
6817               } else {
6818                   widget.ub[0] = iter[0];
6819                   widget.ub[1] = iter[1];
6820               }
6821               if (type == GL_SHORT) {
6822                   if (indexFormat) {
6823                       *iter2++ = widget.s[0];
6824                   } else {
6825                       /* rough approx */
6826                       *iter2++ = widget.s[0]*2;
6827                   }
6828               } else {
6829                   *iter2++ = widget.us[0];
6830               }
6831               break;
6832             case GL_UNSIGNED_INT_8_8_8_8:               
6833               extract8888(myswapBytes,iter,extractComponents);
6834               for (k = 0; k < 4; k++) {
6835                 *iter2++ = (GLushort)(extractComponents[k]*65535);
6836               }
6837               break;
6838             case GL_UNSIGNED_INT_8_8_8_8_REV:           
6839               extract8888rev(myswapBytes,iter,extractComponents);
6840               for (k = 0; k < 4; k++) {
6841                 *iter2++ = (GLushort)(extractComponents[k]*65535);
6842               }
6843               break;
6844             case GL_UNSIGNED_INT_10_10_10_2:            
6845               extract1010102(myswapBytes,iter,extractComponents);
6846               for (k = 0; k < 4; k++) {
6847                 *iter2++ = (GLushort)(extractComponents[k]*65535);
6848               }
6849               break;
6850             case GL_UNSIGNED_INT_2_10_10_10_REV:
6851               extract2101010rev(myswapBytes,iter,extractComponents);
6852               for (k = 0; k < 4; k++) {
6853                 *iter2++ = (GLushort)(extractComponents[k]*65535);
6854               }
6855               break;
6856             case GL_INT:
6857             case GL_UNSIGNED_INT:
6858             case GL_FLOAT:
6859               if (myswapBytes) {
6860                   widget.ub[0] = iter[3];
6861                   widget.ub[1] = iter[2];
6862                   widget.ub[2] = iter[1];
6863                   widget.ub[3] = iter[0];
6864               } else {
6865                   widget.ub[0] = iter[0];
6866                   widget.ub[1] = iter[1];
6867                   widget.ub[2] = iter[2];
6868                   widget.ub[3] = iter[3];
6869               }
6870               if (type == GL_FLOAT) {
6871                   if (indexFormat) {
6872                       *iter2++ = widget.f;
6873                   } else {
6874                       *iter2++ = 65535 * widget.f;
6875                   }
6876               } else if (type == GL_UNSIGNED_INT) {
6877                   if (indexFormat) {
6878                       *iter2++ = widget.ui;
6879                   } else {
6880                       *iter2++ = widget.ui >> 16;
6881                   }
6882               } else {
6883                   if (indexFormat) {
6884                       *iter2++ = widget.i;
6885                   } else {
6886                       *iter2++ = widget.i >> 15;
6887                   }
6888               }
6889               break;
6890             default:
6891               assert(0);
6892             }
6893
6894             iter+= elementSize;
6895          } /* for ww */
6896          rowStart+= rowSize;
6897
6898          iter= rowStart;        /* for assertion purposes */
6899       } /* for hh */
6900
6901       start+= imageSize;
6902    } /* for dd */
6903
6904    /* iterators should be one byte past end */
6905    if (!isTypePackedPixel(type)) {
6906       assert(iter2 == &newImage[width*height*depth*components]);
6907    }
6908    else {
6909       assert(iter2 == &newImage[width*height*depth*
6910                                 elements_per_group(format,0)]);
6911    }
6912    assert( iter == &((const GLubyte *)userImage)[rowSize*height*depth +
6913                                         psm->unpack_skip_rows * rowSize +
6914                                         psm->unpack_skip_pixels * groupSize +
6915                                         /*3dstuff*/
6916                                         psm->unpack_skip_images * imageSize] );
6917 } /* fillImage3D () */
6918
6919 static void scaleInternal3D(GLint components,
6920                             GLint widthIn, GLint heightIn, GLint depthIn,
6921                             const GLushort *dataIn,
6922                             GLint widthOut, GLint heightOut, GLint depthOut,
6923                             GLushort *dataOut)
6924 {
6925     float x, lowx, highx, convx, halfconvx;
6926     float y, lowy, highy, convy, halfconvy;
6927     float z, lowz, highz, convz, halfconvz;
6928     float xpercent,ypercent,zpercent;
6929     float percent;
6930     /* Max components in a format is 4, so... */
6931     float totals[4];
6932     float volume;
6933     int i,j,d,k,zint,yint,xint,xindex,yindex,zindex;
6934     int temp;
6935
6936     convz = (float) depthIn/depthOut;
6937     convy = (float) heightIn/heightOut;
6938     convx = (float) widthIn/widthOut;
6939     halfconvx = convx/2;
6940     halfconvy = convy/2;
6941     halfconvz = convz/2;
6942     for (d = 0; d < depthOut; d++) {
6943        z = convz * (d+0.5);
6944        if (depthIn > depthOut) {
6945            highz = z + halfconvz;
6946            lowz = z - halfconvz;
6947        } else {
6948            highz = z + 0.5;
6949            lowz = z - 0.5;
6950        }
6951        for (i = 0; i < heightOut; i++) {
6952            y = convy * (i+0.5);
6953            if (heightIn > heightOut) {
6954                highy = y + halfconvy;
6955                lowy = y - halfconvy;
6956            } else {
6957                highy = y + 0.5;
6958                lowy = y - 0.5;
6959            }
6960            for (j = 0; j < widthOut; j++) {
6961                x = convx * (j+0.5);
6962                if (widthIn > widthOut) {
6963                    highx = x + halfconvx;
6964                    lowx = x - halfconvx;
6965                } else {
6966                    highx = x + 0.5;
6967                    lowx = x - 0.5;
6968                }
6969
6970                /*
6971                ** Ok, now apply box filter to box that goes from (lowx, lowy,
6972                ** lowz) to (highx, highy, highz) on input data into this pixel
6973                ** on output data.
6974                */
6975                totals[0] = totals[1] = totals[2] = totals[3] = 0.0;
6976                volume = 0.0;
6977
6978                z = lowz;
6979                zint = floor(z);
6980                while (z < highz) {
6981                   zindex = (zint + depthIn) % depthIn;
6982                   if (highz < zint+1) {
6983                       zpercent = highz - z;
6984                   } else {
6985                       zpercent = zint+1 - z;
6986                   }
6987
6988                   y = lowy;
6989                   yint = floor(y);
6990                   while (y < highy) {
6991                       yindex = (yint + heightIn) % heightIn;
6992                       if (highy < yint+1) {
6993                           ypercent = highy - y;
6994                       } else {
6995                           ypercent = yint+1 - y;
6996                       }
6997
6998                       x = lowx;
6999                       xint = floor(x);
7000
7001                       while (x < highx) {
7002                           xindex = (xint + widthIn) % widthIn;
7003                           if (highx < xint+1) {
7004                               xpercent = highx - x;
7005                           } else {
7006                               xpercent = xint+1 - x;
7007                           }
7008
7009                           percent = xpercent * ypercent * zpercent;
7010                           volume += percent;
7011
7012                           temp = (xindex + (yindex*widthIn) +
7013                                   (zindex*widthIn*heightIn)) * components;
7014                           for (k = 0; k < components; k++) {
7015                               assert(0 <= (temp+k) &&
7016                                      (temp+k) <
7017                                      (widthIn*heightIn*depthIn*components));
7018                               totals[k] += dataIn[temp + k] * percent;
7019                           }
7020
7021                           xint++;
7022                           x = xint;
7023                       } /* while x */
7024
7025                       yint++;
7026                       y = yint;
7027                   } /* while y */
7028
7029                   zint++;
7030                   z = zint;
7031                } /* while z */
7032
7033                temp = (j + (i * widthOut) +
7034                        (d*widthOut*heightOut)) * components;
7035                for (k = 0; k < components; k++) {
7036                    /* totals[] should be rounded in the case of enlarging an
7037                     * RGB ramp when the type is 332 or 4444
7038                     */
7039                    assert(0 <= (temp+k) &&
7040                           (temp+k) < (widthOut*heightOut*depthOut*components));
7041                    dataOut[temp + k] = (totals[k]+0.5)/volume;
7042                }
7043            } /* for j */
7044        } /* for i */
7045     } /* for d */
7046 } /* scaleInternal3D() */
7047
7048 static void emptyImage3D(const PixelStorageModes *psm,
7049                          GLint width, GLint height, GLint depth,
7050                          GLenum format, GLenum type, GLboolean indexFormat,
7051                          const GLushort *oldImage, void *userImage)
7052 {
7053    int myswapBytes;
7054    int components;
7055    int groupsPerLine;
7056    int elementSize;
7057    int groupSize;
7058    int rowSize;
7059    int padding;
7060    GLubyte *start, *rowStart, *iter;
7061    int elementsPerLine;
7062    const GLushort *iter2;
7063    int ii, jj, dd, k;
7064    int rowsPerImage;
7065    int imageSize;
7066
7067    myswapBytes= psm->pack_swap_bytes;
7068    components = elements_per_group(format,type);
7069    if (psm->pack_row_length > 0) {
7070       groupsPerLine = psm->pack_row_length;
7071    }
7072    else {
7073       groupsPerLine = width;
7074    }
7075
7076    elementSize= bytes_per_element(type);
7077    groupSize= elementSize * components;
7078    if (elementSize == 1) myswapBytes= 0;
7079
7080    /* 3dstuff begin */
7081    if (psm->pack_image_height > 0) {
7082       rowsPerImage= psm->pack_image_height;
7083    }
7084    else {
7085       rowsPerImage= height;
7086    }
7087
7088    /* 3dstuff end */
7089
7090    rowSize = groupsPerLine * groupSize;
7091    padding = rowSize % psm->pack_alignment;
7092    if (padding) {
7093       rowSize+= psm->pack_alignment - padding;
7094    }
7095
7096    imageSize= rowsPerImage * rowSize; /* 3dstuff */
7097
7098    start = (GLubyte *)userImage + psm->pack_skip_rows * rowSize +
7099                                   psm->pack_skip_pixels * groupSize +
7100                                   /*3dstuff*/
7101                                   psm->pack_skip_images * imageSize;
7102    elementsPerLine= width * components;
7103
7104    iter2 = oldImage;
7105    for (dd= 0; dd < depth; dd++) {
7106       rowStart= start;
7107
7108       for (ii= 0; ii< height; ii++) {
7109          iter = rowStart;
7110
7111          for (jj = 0; jj < elementsPerLine; jj++) {
7112             Type_Widget widget;
7113             float shoveComponents[4];
7114
7115             switch(type){
7116             case GL_UNSIGNED_BYTE:
7117               if (indexFormat) {
7118                   *iter = *iter2++;
7119               } else {
7120                   *iter = *iter2++ >> 8;
7121               }
7122               break;
7123             case GL_BYTE:
7124               if (indexFormat) {
7125                   *((GLbyte *) iter) = *iter2++;
7126               } else {
7127                   *((GLbyte *) iter) = *iter2++ >> 9;
7128               }
7129               break;
7130             case GL_UNSIGNED_BYTE_3_3_2:
7131               for (k = 0; k < 3; k++) {
7132                  shoveComponents[k]= *iter2++ / 65535.0;
7133               }
7134               shove332(shoveComponents,0,(void *)iter);
7135               break;
7136             case GL_UNSIGNED_BYTE_2_3_3_REV:
7137               for (k = 0; k < 3; k++) {
7138                  shoveComponents[k]= *iter2++ / 65535.0;
7139               }
7140               shove233rev(shoveComponents,0,(void *)iter);
7141               break;
7142             case GL_UNSIGNED_SHORT_5_6_5:               
7143               for (k = 0; k < 3; k++) {
7144                  shoveComponents[k]= *iter2++ / 65535.0;
7145               }
7146               shove565(shoveComponents,0,(void *)&widget.us[0]);
7147               if (myswapBytes) {
7148                  iter[0] = widget.ub[1];
7149                  iter[1] = widget.ub[0];
7150               }
7151               else {
7152                  *(GLushort *)iter = widget.us[0];
7153               }
7154               break;
7155             case GL_UNSIGNED_SHORT_5_6_5_REV:           
7156               for (k = 0; k < 3; k++) {
7157                  shoveComponents[k]= *iter2++ / 65535.0;
7158               }
7159               shove565rev(shoveComponents,0,(void *)&widget.us[0]);
7160               if (myswapBytes) {
7161                  iter[0] = widget.ub[1];
7162                  iter[1] = widget.ub[0];
7163               }
7164               else {
7165                  *(GLushort *)iter = widget.us[0];
7166               }
7167               break;
7168             case GL_UNSIGNED_SHORT_4_4_4_4:
7169               for (k = 0; k < 4; k++) {
7170                  shoveComponents[k]= *iter2++ / 65535.0;
7171               }
7172               shove4444(shoveComponents,0,(void *)&widget.us[0]);
7173               if (myswapBytes) {
7174                  iter[0] = widget.ub[1];
7175                  iter[1] = widget.ub[0];
7176               } else {
7177                  *(GLushort *)iter = widget.us[0];
7178               }
7179               break;
7180             case GL_UNSIGNED_SHORT_4_4_4_4_REV:
7181               for (k = 0; k < 4; k++) {
7182                  shoveComponents[k]= *iter2++ / 65535.0;
7183               }
7184               shove4444rev(shoveComponents,0,(void *)&widget.us[0]);
7185               if (myswapBytes) {
7186                  iter[0] = widget.ub[1];
7187                  iter[1] = widget.ub[0];
7188               } else {
7189                  *(GLushort *)iter = widget.us[0];
7190               }
7191               break;
7192             case GL_UNSIGNED_SHORT_5_5_5_1:
7193               for (k = 0; k < 4; k++) {
7194                  shoveComponents[k]= *iter2++ / 65535.0;
7195               }
7196               shove5551(shoveComponents,0,(void *)&widget.us[0]);
7197               if (myswapBytes) {
7198                  iter[0] = widget.ub[1];
7199                  iter[1] = widget.ub[0];
7200               } else {
7201                  *(GLushort *)iter = widget.us[0];
7202               }
7203               break;
7204             case GL_UNSIGNED_SHORT_1_5_5_5_REV:
7205               for (k = 0; k < 4; k++) {
7206                  shoveComponents[k]= *iter2++ / 65535.0;
7207               }
7208               shove1555rev(shoveComponents,0,(void *)&widget.us[0]);
7209               if (myswapBytes) {
7210                  iter[0] = widget.ub[1];
7211                  iter[1] = widget.ub[0];
7212               } else {
7213                  *(GLushort *)iter = widget.us[0];
7214               }
7215               break;
7216             case GL_UNSIGNED_SHORT:
7217             case GL_SHORT:
7218               if (type == GL_SHORT) {
7219                   if (indexFormat) {
7220                       widget.s[0] = *iter2++;
7221                   } else {
7222                       widget.s[0] = *iter2++ >> 1;
7223                   }
7224               } else {
7225                   widget.us[0] = *iter2++;
7226               }
7227               if (myswapBytes) {
7228                   iter[0] = widget.ub[1];
7229                   iter[1] = widget.ub[0];
7230               } else {
7231                   iter[0] = widget.ub[0];
7232                   iter[1] = widget.ub[1];
7233               }
7234               break;
7235             case GL_UNSIGNED_INT_8_8_8_8:
7236                for (k = 0; k < 4; k++) {
7237                   shoveComponents[k]= *iter2++ / 65535.0;
7238                }
7239                shove8888(shoveComponents,0,(void *)&widget.ui);
7240                if (myswapBytes) {
7241                    iter[3] = widget.ub[0];
7242                    iter[2] = widget.ub[1];
7243                    iter[1] = widget.ub[2];
7244                    iter[0] = widget.ub[3];
7245                } else {
7246                    *(GLuint *)iter= widget.ui;
7247                }
7248                break;
7249             case GL_UNSIGNED_INT_8_8_8_8_REV:
7250                for (k = 0; k < 4; k++) {
7251                   shoveComponents[k]= *iter2++ / 65535.0;
7252                }
7253                shove8888rev(shoveComponents,0,(void *)&widget.ui);
7254                if (myswapBytes) {
7255                    iter[3] = widget.ub[0];
7256                    iter[2] = widget.ub[1];
7257                    iter[1] = widget.ub[2];
7258                    iter[0] = widget.ub[3];
7259                } else {
7260                    *(GLuint *)iter= widget.ui;
7261                }
7262                break;
7263             case GL_UNSIGNED_INT_10_10_10_2:
7264                for (k = 0; k < 4; k++) {
7265                   shoveComponents[k]= *iter2++ / 65535.0;
7266                }
7267                shove1010102(shoveComponents,0,(void *)&widget.ui);
7268                if (myswapBytes) {
7269                    iter[3] = widget.ub[0];
7270                    iter[2] = widget.ub[1];
7271                    iter[1] = widget.ub[2];
7272                    iter[0] = widget.ub[3];
7273                } else {
7274                    *(GLuint *)iter= widget.ui;
7275                }
7276                break;
7277             case GL_UNSIGNED_INT_2_10_10_10_REV:
7278                for (k = 0; k < 4; k++) {
7279                   shoveComponents[k]= *iter2++ / 65535.0;
7280                }
7281                shove2101010rev(shoveComponents,0,(void *)&widget.ui);
7282                if (myswapBytes) {
7283                    iter[3] = widget.ub[0];
7284                    iter[2] = widget.ub[1];
7285                    iter[1] = widget.ub[2];
7286                    iter[0] = widget.ub[3];
7287                } else {
7288                    *(GLuint *)iter= widget.ui;
7289                }
7290                break;
7291             case GL_INT:
7292             case GL_UNSIGNED_INT:
7293             case GL_FLOAT:
7294               if (type == GL_FLOAT) {
7295                   if (indexFormat) {
7296                       widget.f = *iter2++;
7297                   } else {
7298                       widget.f = *iter2++ / (float) 65535.0;
7299                   }
7300               } else if (type == GL_UNSIGNED_INT) {
7301                   if (indexFormat) {
7302                       widget.ui = *iter2++;
7303                   } else {
7304                       widget.ui = (unsigned int) *iter2++ * 65537;
7305                   }
7306               } else {
7307                   if (indexFormat) {
7308                       widget.i = *iter2++;
7309                   } else {
7310                       widget.i = ((unsigned int) *iter2++ * 65537)/2;
7311                   }
7312               }
7313               if (myswapBytes) {
7314                   iter[3] = widget.ub[0];
7315                   iter[2] = widget.ub[1];
7316                   iter[1] = widget.ub[2];
7317                   iter[0] = widget.ub[3];
7318               } else {
7319                   iter[0] = widget.ub[0];
7320                   iter[1] = widget.ub[1];
7321                   iter[2] = widget.ub[2];
7322                   iter[3] = widget.ub[3];
7323               }
7324               break;
7325             default:
7326                assert(0);
7327             }
7328
7329             iter+= elementSize;
7330          }  /* for jj */
7331
7332          rowStart+= rowSize;
7333       } /* for ii */
7334
7335       start+= imageSize;
7336    } /* for dd */
7337
7338    /* iterators should be one byte past end */
7339    if (!isTypePackedPixel(type)) {
7340       assert(iter2 == &oldImage[width*height*depth*components]);
7341    }
7342    else {
7343       assert(iter2 == &oldImage[width*height*depth*
7344                                 elements_per_group(format,0)]);
7345    }
7346    assert( iter == &((GLubyte *)userImage)[rowSize*height*depth +
7347                                         psm->unpack_skip_rows * rowSize +
7348                                         psm->unpack_skip_pixels * groupSize +
7349                                         /*3dstuff*/
7350                                         psm->unpack_skip_images * imageSize] );
7351 } /* emptyImage3D() */
7352
7353 static
7354 int gluScaleImage3D(GLenum format,
7355                     GLint widthIn, GLint heightIn, GLint depthIn,
7356                     GLenum typeIn, const void *dataIn,
7357                     GLint widthOut, GLint heightOut, GLint depthOut,
7358                     GLenum typeOut, void *dataOut)
7359 {
7360    int components;
7361    GLushort *beforeImage, *afterImage;
7362    PixelStorageModes psm;
7363
7364    if (widthIn == 0 || heightIn == 0 || depthIn == 0 ||
7365        widthOut == 0 || heightOut == 0 || depthOut == 0) {
7366       return 0;
7367    }
7368
7369    if (widthIn < 0 || heightIn < 0 || depthIn < 0 ||
7370        widthOut < 0 || heightOut < 0 || depthOut < 0) {
7371       return GLU_INVALID_VALUE;
7372    }
7373
7374    if (!legalFormat(format) || !legalType(typeIn) || !legalType(typeOut) ||
7375        typeIn == GL_BITMAP || typeOut == GL_BITMAP) {
7376       return GLU_INVALID_ENUM;
7377    }
7378    if (!isLegalFormatForPackedPixelType(format, typeIn)) {
7379       return GLU_INVALID_OPERATION;
7380    }
7381    if (!isLegalFormatForPackedPixelType(format, typeOut)) {
7382       return GLU_INVALID_OPERATION;
7383    }
7384
7385    beforeImage = malloc(imageSize3D(widthIn, heightIn, depthIn, format,
7386                                     GL_UNSIGNED_SHORT));
7387    afterImage = malloc(imageSize3D(widthOut, heightOut, depthOut, format,
7388                                    GL_UNSIGNED_SHORT));
7389    if (beforeImage == NULL || afterImage == NULL) {
7390        free(beforeImage);
7391        free(afterImage);
7392        return GLU_OUT_OF_MEMORY;
7393    }
7394    retrieveStoreModes3D(&psm);
7395
7396    fillImage3D(&psm,widthIn,heightIn,depthIn,format,typeIn, is_index(format),
7397                dataIn, beforeImage);
7398    components = elements_per_group(format,0);
7399    scaleInternal3D(components,widthIn,heightIn,depthIn,beforeImage,
7400                    widthOut,heightOut,depthOut,afterImage);
7401    emptyImage3D(&psm,widthOut,heightOut,depthOut,format,typeOut,
7402                 is_index(format),afterImage, dataOut);
7403    free((void *) beforeImage);
7404    free((void *) afterImage);
7405
7406    return 0;
7407 } /* gluScaleImage3D() */
7408
7409
7410 static void closestFit3D(GLenum target, GLint width, GLint height, GLint depth,
7411                          GLint internalFormat, GLenum format, GLenum type,
7412                          GLint *newWidth, GLint *newHeight, GLint *newDepth)
7413 {
7414    GLint widthPowerOf2= nearestPower(width);
7415    GLint heightPowerOf2= nearestPower(height);          
7416    GLint depthPowerOf2= nearestPower(depth);
7417    GLint proxyWidth;
7418
7419    do {
7420       /* compute level 1 width & height & depth, clamping each at 1 */
7421       GLint widthAtLevelOne= (widthPowerOf2 > 1) ?
7422                               widthPowerOf2 >> 1 :
7423                               widthPowerOf2;
7424       GLint heightAtLevelOne= (heightPowerOf2 > 1) ?
7425                                heightPowerOf2 >> 1 :
7426                                heightPowerOf2;
7427       GLint depthAtLevelOne= (depthPowerOf2 > 1) ?
7428                               depthPowerOf2 >> 1 :
7429                               depthPowerOf2;
7430       GLenum proxyTarget = GL_PROXY_TEXTURE_3D;
7431       assert(widthAtLevelOne > 0);
7432       assert(heightAtLevelOne > 0);
7433       assert(depthAtLevelOne > 0);
7434
7435       /* does width x height x depth at level 1 & all their mipmaps fit? */
7436       assert(target == GL_TEXTURE_3D || target == GL_PROXY_TEXTURE_3D);
7437       gluTexImage3D(proxyTarget, 1, /* must be non-zero */
7438                     internalFormat,
7439                     widthAtLevelOne,heightAtLevelOne,depthAtLevelOne,
7440                     0,format,type,NULL);
7441       glGetTexLevelParameteriv(proxyTarget, 1,GL_TEXTURE_WIDTH,&proxyWidth);
7442       /* does it fit??? */
7443       if (proxyWidth == 0) { /* nope, so try again with these sizes */
7444          if (widthPowerOf2 == 1 && heightPowerOf2 == 1 &&
7445              depthPowerOf2 == 1) {
7446             *newWidth= *newHeight= *newDepth= 1; /* must fit 1x1x1 texture */
7447             return;
7448          }
7449          widthPowerOf2= widthAtLevelOne;
7450          heightPowerOf2= heightAtLevelOne;
7451          depthPowerOf2= depthAtLevelOne;
7452       }
7453       /* else it does fit */
7454    } while (proxyWidth == 0);
7455    /* loop must terminate! */
7456
7457    /* return the width & height at level 0 that fits */
7458    *newWidth= widthPowerOf2;
7459    *newHeight= heightPowerOf2;
7460    *newDepth= depthPowerOf2;
7461 /*printf("Proxy Textures\n");*/
7462 } /* closestFit3D() */
7463
7464 static void halveImagePackedPixelSlice(int components,
7465                                        void (*extractPackedPixel)
7466                                        (int, const void *,GLfloat []),
7467                                        void (*shovePackedPixel)
7468                                        (const GLfloat [],int, void *),
7469                                        GLint width, GLint height, GLint depth,
7470                                        const void *dataIn, void *dataOut,
7471                                        GLint pixelSizeInBytes,
7472                                        GLint rowSizeInBytes,
7473                                        GLint imageSizeInBytes,
7474                                        GLint isSwap)
7475 {
7476    int ii, jj;
7477    int halfWidth= width / 2;
7478    int halfHeight= height / 2;
7479    int halfDepth= depth / 2;
7480    const char *src= (const char *)dataIn;
7481    int outIndex= 0;
7482
7483    assert((width == 1 || height == 1) && depth >= 2);
7484
7485    if (width == height) {       /* a 1-pixel column viewed from top */
7486       assert(width == 1 && height == 1);
7487       assert(depth >= 2);
7488
7489       for (ii= 0; ii< halfDepth; ii++) {
7490          float totals[4];
7491          float extractTotals[BOX2][4];
7492          int cc;
7493
7494          (*extractPackedPixel)(isSwap,src,&extractTotals[0][0]);
7495          (*extractPackedPixel)(isSwap,(src+imageSizeInBytes),
7496                                &extractTotals[1][0]);
7497          for (cc = 0; cc < components; cc++) {
7498             int kk;
7499
7500             /* average 2 pixels since only a column */
7501             totals[cc]= 0.0;
7502             /* totals[RED]= extractTotals[0][RED]+extractTotals[1][RED];
7503              * totals[RED]/= 2.0;
7504              */
7505             for (kk = 0; kk < BOX2; kk++) {
7506               totals[cc]+= extractTotals[kk][cc];
7507             }
7508             totals[cc]/= (float)BOX2;
7509          } /* for cc */
7510         
7511          (*shovePackedPixel)(totals,outIndex,dataOut);
7512          outIndex++;
7513          /* skip over to next group of 2 */
7514          src+= imageSizeInBytes + imageSizeInBytes;
7515       } /* for ii */
7516    }
7517    else if (height == 1) {      /* horizontal slice viewed from top */
7518       assert(width != 1);
7519
7520       for (ii= 0; ii< halfDepth; ii++) {
7521          for (jj= 0; jj< halfWidth; jj++) {
7522              float totals[4];
7523              float extractTotals[BOX4][4];
7524              int cc;
7525
7526              (*extractPackedPixel)(isSwap,src,
7527                                    &extractTotals[0][0]);
7528              (*extractPackedPixel)(isSwap,(src+pixelSizeInBytes),
7529                                    &extractTotals[1][0]);
7530              (*extractPackedPixel)(isSwap,(src+imageSizeInBytes),
7531                                    &extractTotals[2][0]);
7532              (*extractPackedPixel)(isSwap,
7533                                    (src+imageSizeInBytes+pixelSizeInBytes),
7534                                    &extractTotals[3][0]);
7535              for (cc = 0; cc < components; cc++) {
7536                 int kk;
7537
7538                 /* grab 4 pixels to average */
7539                 totals[cc]= 0.0;
7540                 /* totals[RED]= extractTotals[0][RED]+extractTotals[1][RED]+
7541                  *              extractTotals[2][RED]+extractTotals[3][RED];
7542                  * totals[RED]/= 4.0;
7543                  */
7544                 for (kk = 0; kk < BOX4; kk++) {
7545                    totals[cc]+= extractTotals[kk][cc];
7546                 }
7547                 totals[cc]/= (float)BOX4;
7548              }
7549              (*shovePackedPixel)(totals,outIndex,dataOut);
7550
7551              outIndex++;
7552              /* skip over to next horizontal square of 4 */
7553              src+= imageSizeInBytes + imageSizeInBytes;
7554          }
7555       }
7556
7557       /* assert() */
7558    }
7559    else if (width == 1) {       /* vertical slice viewed from top */
7560       assert(height != 1);
7561
7562       for (ii= 0; ii< halfDepth; ii++) {
7563          for (jj= 0; jj< halfHeight; jj++) {
7564             float totals[4];
7565             float extractTotals[BOX4][4];
7566             int cc;
7567
7568             (*extractPackedPixel)(isSwap,src,
7569                                   &extractTotals[0][0]);
7570             (*extractPackedPixel)(isSwap,(src+rowSizeInBytes),
7571                                   &extractTotals[1][0]);
7572             (*extractPackedPixel)(isSwap,(src+imageSizeInBytes),
7573                                   &extractTotals[2][0]);
7574             (*extractPackedPixel)(isSwap,
7575                                   (src+imageSizeInBytes+rowSizeInBytes),
7576                                   &extractTotals[3][0]);
7577             for (cc = 0; cc < components; cc++) {
7578                int kk;
7579
7580                /* grab 4 pixels to average */
7581                totals[cc]= 0.0;
7582                /* totals[RED]= extractTotals[0][RED]+extractTotals[1][RED]+
7583                 *              extractTotals[2][RED]+extractTotals[3][RED];
7584                 * totals[RED]/= 4.0;
7585                 */
7586                for (kk = 0; kk < BOX4; kk++) {
7587                   totals[cc]+= extractTotals[kk][cc];
7588                }
7589                totals[cc]/= (float)BOX4;
7590             }
7591             (*shovePackedPixel)(totals,outIndex,dataOut);
7592
7593             outIndex++;
7594
7595             /* skip over to next vertical square of 4 */
7596             src+= imageSizeInBytes + imageSizeInBytes;
7597          }
7598       }
7599       /* assert() */
7600    }
7601
7602 } /* halveImagePackedPixelSlice() */
7603
7604 static void halveImagePackedPixel3D(int components,
7605                                     void (*extractPackedPixel)
7606                                     (int, const void *,GLfloat []),
7607                                     void (*shovePackedPixel)
7608                                     (const GLfloat [],int, void *),
7609                                     GLint width, GLint height, GLint depth,
7610                                     const void *dataIn, void *dataOut,
7611                                     GLint pixelSizeInBytes,
7612                                     GLint rowSizeInBytes,
7613                                     GLint imageSizeInBytes,
7614                                     GLint isSwap)
7615 {
7616    if (depth == 1) {
7617       assert(1 <= width && 1 <= height);
7618
7619       halveImagePackedPixel(components,extractPackedPixel,shovePackedPixel,
7620                             width,height,dataIn,dataOut,pixelSizeInBytes,
7621                             rowSizeInBytes,isSwap);
7622       return;
7623    }
7624    /* a horizontal or vertical slice viewed from top */
7625    else if (width == 1 || height == 1) {
7626       assert(1 <= depth);
7627
7628       halveImagePackedPixelSlice(components,
7629                                  extractPackedPixel,shovePackedPixel,
7630                                  width, height, depth, dataIn, dataOut,
7631                                  pixelSizeInBytes, rowSizeInBytes,
7632                                  imageSizeInBytes, isSwap);
7633       return;
7634    }
7635    {
7636       int ii, jj, dd;
7637
7638       int halfWidth= width / 2;
7639       int halfHeight= height / 2;
7640       int halfDepth= depth / 2;
7641       const char *src= (const char *) dataIn;
7642       int padBytes= rowSizeInBytes - (width*pixelSizeInBytes);
7643       int outIndex= 0;
7644
7645       for (dd= 0; dd < halfDepth; dd++) {
7646          for (ii= 0; ii< halfHeight; ii++) {
7647             for (jj= 0; jj< halfWidth; jj++) {
7648 #define BOX8 8
7649                float totals[4]; /* 4 is maximum components */
7650                float extractTotals[BOX8][4]; /* 4 is maximum components */
7651                int cc;
7652
7653                (*extractPackedPixel)(isSwap,src,
7654                                      &extractTotals[0][0]);
7655                (*extractPackedPixel)(isSwap,(src+pixelSizeInBytes),
7656                                      &extractTotals[1][0]);
7657                (*extractPackedPixel)(isSwap,(src+rowSizeInBytes),
7658                                      &extractTotals[2][0]);
7659                (*extractPackedPixel)(isSwap,
7660                                      (src+rowSizeInBytes+pixelSizeInBytes),
7661                                      &extractTotals[3][0]);
7662
7663                (*extractPackedPixel)(isSwap,(src+imageSizeInBytes),
7664                                      &extractTotals[4][0]);
7665                (*extractPackedPixel)(isSwap,(src+pixelSizeInBytes+imageSizeInBytes),
7666                                      &extractTotals[5][0]);
7667                (*extractPackedPixel)(isSwap,(src+rowSizeInBytes+imageSizeInBytes),
7668                                      &extractTotals[6][0]);
7669                (*extractPackedPixel)(isSwap,
7670                                      (src+rowSizeInBytes+pixelSizeInBytes+imageSizeInBytes),
7671                                      &extractTotals[7][0]);
7672                for (cc = 0; cc < components; cc++) {
7673                   int kk;
7674
7675                   /* grab 8 pixels to average */
7676                   totals[cc]= 0.0;
7677                   /* totals[RED]= extractTotals[0][RED]+extractTotals[1][RED]+
7678                    *              extractTotals[2][RED]+extractTotals[3][RED]+
7679                    *              extractTotals[4][RED]+extractTotals[5][RED]+
7680                    *              extractTotals[6][RED]+extractTotals[7][RED];
7681                    * totals[RED]/= 8.0;
7682                    */
7683                   for (kk = 0; kk < BOX8; kk++) {
7684                      totals[cc]+= extractTotals[kk][cc];
7685                   }
7686                   totals[cc]/= (float)BOX8;
7687                }
7688                (*shovePackedPixel)(totals,outIndex,dataOut);
7689
7690                outIndex++;
7691                /* skip over to next square of 4 */
7692                src+= pixelSizeInBytes + pixelSizeInBytes;
7693             }
7694             /* skip past pad bytes, if any, to get to next row */
7695             src+= padBytes;
7696
7697             /* src is at beginning of a row here, but it's the second row of
7698              * the square block of 4 pixels that we just worked on so we
7699              * need to go one more row.
7700              * i.e.,
7701              *                   OO...
7702              *           here -->OO...
7703              *       but want -->OO...
7704              *                   OO...
7705              *                   ...
7706              */
7707             src+= rowSizeInBytes;
7708          }
7709
7710          src+= imageSizeInBytes;
7711       } /* for dd */
7712
7713       /* both pointers must reach one byte after the end */
7714       assert(src == &((const char *)dataIn)[rowSizeInBytes*height*depth]);
7715       assert(outIndex == halfWidth * halfHeight * halfDepth);
7716    } /* for dd */
7717
7718 } /* halveImagePackedPixel3D() */
7719
7720 static int gluBuild3DMipmapLevelsCore(GLenum target, GLint internalFormat,
7721                                       GLsizei width,
7722                                       GLsizei height,
7723                                       GLsizei depth,
7724                                       GLsizei widthPowerOf2,
7725                                       GLsizei heightPowerOf2,
7726                                       GLsizei depthPowerOf2,
7727                                       GLenum format, GLenum type,
7728                                       GLint userLevel,
7729                                       GLint baseLevel,GLint maxLevel,
7730                                       const void *data)
7731 {
7732    GLint newWidth, newHeight, newDepth;
7733    GLint level, levels;
7734    const void *usersImage;
7735    void *srcImage, *dstImage;
7736    __GLU_INIT_SWAP_IMAGE;
7737    GLint memReq;
7738    GLint cmpts;
7739
7740    GLint myswapBytes, groupsPerLine, elementSize, groupSize;
7741    GLint rowsPerImage, imageSize;
7742    GLint rowSize, padding;
7743    PixelStorageModes psm;
7744
7745    assert(checkMipmapArgs(internalFormat,format,type) == 0);
7746    assert(width >= 1 && height >= 1 && depth >= 1);
7747    assert(type != GL_BITMAP);
7748
7749    srcImage = dstImage = NULL;
7750
7751    newWidth= widthPowerOf2;
7752    newHeight= heightPowerOf2;
7753    newDepth= depthPowerOf2;
7754    levels = computeLog(newWidth);
7755    level = computeLog(newHeight);
7756    if (level > levels) levels=level;
7757    level = computeLog(newDepth);
7758    if (level > levels) levels=level;
7759
7760    levels+= userLevel;
7761
7762    retrieveStoreModes3D(&psm);
7763    myswapBytes = psm.unpack_swap_bytes;
7764    cmpts = elements_per_group(format,type);
7765    if (psm.unpack_row_length > 0) {
7766        groupsPerLine = psm.unpack_row_length;
7767    } else {
7768        groupsPerLine = width;
7769    }
7770
7771    elementSize = bytes_per_element(type);
7772    groupSize = elementSize * cmpts;
7773    if (elementSize == 1) myswapBytes = 0;
7774
7775    /* 3dstuff begin */
7776    if (psm.unpack_image_height > 0) {
7777       rowsPerImage= psm.unpack_image_height;
7778    }
7779    else {
7780       rowsPerImage= height;
7781    }
7782
7783    /* 3dstuff end */
7784    rowSize = groupsPerLine * groupSize;
7785    padding = (rowSize % psm.unpack_alignment);
7786    if (padding) {
7787        rowSize += psm.unpack_alignment - padding;
7788    }
7789
7790    imageSize= rowsPerImage * rowSize; /* 3dstuff */
7791
7792    usersImage = (const GLubyte *)data + psm.unpack_skip_rows * rowSize +
7793                                   psm.unpack_skip_pixels * groupSize +
7794                                   /* 3dstuff */
7795                                   psm.unpack_skip_images * imageSize;
7796
7797    glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
7798    glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
7799    glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
7800    glPixelStorei(GL_UNPACK_SKIP_IMAGES, 0);
7801    glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, 0);
7802
7803    level = userLevel;
7804
7805    if (width == newWidth && height == newHeight && depth == newDepth) {
7806        /* Use usersImage for level userLevel */
7807        if (baseLevel <= level && level <= maxLevel) {
7808           gluTexImage3D(target, level, internalFormat, width,
7809                        height, depth, 0, format, type,
7810                        usersImage);
7811        }
7812        if(levels == 0) { /* we're done. clean up and return */
7813          glPixelStorei(GL_UNPACK_ALIGNMENT, psm.unpack_alignment);
7814          glPixelStorei(GL_UNPACK_SKIP_ROWS, psm.unpack_skip_rows);
7815          glPixelStorei(GL_UNPACK_SKIP_PIXELS, psm.unpack_skip_pixels);
7816          glPixelStorei(GL_UNPACK_ROW_LENGTH, psm.unpack_row_length);
7817          glPixelStorei(GL_UNPACK_SWAP_BYTES, psm.unpack_swap_bytes);
7818          glPixelStorei(GL_UNPACK_SKIP_IMAGES, psm.unpack_skip_images);
7819          glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, psm.unpack_image_height);
7820          return 0;
7821        }
7822        {
7823           int nextWidth= newWidth/2;
7824           int nextHeight= newHeight/2;
7825           int nextDepth= newDepth/2;
7826
7827           /* clamp to 1 */
7828           if (nextWidth < 1) nextWidth= 1;
7829           if (nextHeight < 1) nextHeight= 1;
7830           if (nextDepth < 1) nextDepth= 1;      
7831        memReq = imageSize3D(nextWidth, nextHeight, nextDepth, format, type);
7832        }
7833        switch(type) {
7834        case GL_UNSIGNED_BYTE:
7835          dstImage = (GLubyte *)malloc(memReq);
7836          break;
7837        case GL_BYTE:
7838          dstImage = (GLbyte *)malloc(memReq);
7839          break;
7840        case GL_UNSIGNED_SHORT:
7841          dstImage = (GLushort *)malloc(memReq);
7842          break;
7843        case GL_SHORT:
7844          dstImage = (GLshort *)malloc(memReq);
7845          break;
7846        case GL_UNSIGNED_INT:
7847          dstImage = (GLuint *)malloc(memReq);
7848          break;
7849        case GL_INT:
7850          dstImage = (GLint *)malloc(memReq);
7851          break;
7852        case GL_FLOAT:
7853          dstImage = (GLfloat *)malloc(memReq);
7854          break;
7855        case GL_UNSIGNED_BYTE_3_3_2:
7856        case GL_UNSIGNED_BYTE_2_3_3_REV:
7857          dstImage = (GLubyte *)malloc(memReq);
7858          break;
7859        case GL_UNSIGNED_SHORT_5_6_5:
7860        case GL_UNSIGNED_SHORT_5_6_5_REV:
7861        case GL_UNSIGNED_SHORT_4_4_4_4:
7862        case GL_UNSIGNED_SHORT_4_4_4_4_REV:
7863        case GL_UNSIGNED_SHORT_5_5_5_1:
7864        case GL_UNSIGNED_SHORT_1_5_5_5_REV:
7865          dstImage = (GLushort *)malloc(memReq);
7866          break;
7867        case GL_UNSIGNED_INT_8_8_8_8:
7868        case GL_UNSIGNED_INT_8_8_8_8_REV:
7869        case GL_UNSIGNED_INT_10_10_10_2:
7870        case GL_UNSIGNED_INT_2_10_10_10_REV:
7871          dstImage = (GLuint *)malloc(memReq);   
7872          break;
7873        default:
7874          return GLU_INVALID_ENUM; /* assertion */
7875        }
7876        if (dstImage == NULL) {
7877          glPixelStorei(GL_UNPACK_ALIGNMENT, psm.unpack_alignment);
7878          glPixelStorei(GL_UNPACK_SKIP_ROWS, psm.unpack_skip_rows);
7879          glPixelStorei(GL_UNPACK_SKIP_PIXELS, psm.unpack_skip_pixels);
7880          glPixelStorei(GL_UNPACK_ROW_LENGTH, psm.unpack_row_length);
7881          glPixelStorei(GL_UNPACK_SWAP_BYTES, psm.unpack_swap_bytes);
7882          glPixelStorei(GL_UNPACK_SKIP_IMAGES, psm.unpack_skip_images);
7883          glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, psm.unpack_image_height);
7884          return GLU_OUT_OF_MEMORY;
7885        }
7886        else
7887          switch(type) {
7888          case GL_UNSIGNED_BYTE:
7889            if (depth > 1) {
7890              halveImage3D(cmpts,extractUbyte,shoveUbyte,
7891                           width,height,depth,
7892                           usersImage,dstImage,elementSize,groupSize,rowSize,
7893                           imageSize,myswapBytes);
7894            }
7895            else {
7896              halveImage_ubyte(cmpts,width,height,usersImage,dstImage,
7897                               elementSize,rowSize,groupSize);
7898            }
7899            break;
7900          case GL_BYTE:
7901            if (depth > 1) {
7902            halveImage3D(cmpts,extractSbyte,shoveSbyte,
7903                         width,height,depth,
7904                         usersImage,dstImage,elementSize,groupSize,rowSize,
7905                         imageSize,myswapBytes);
7906            }
7907            else {
7908              halveImage_byte(cmpts,width,height,usersImage,dstImage,
7909                              elementSize,rowSize,groupSize);
7910            }
7911            break;
7912          case GL_UNSIGNED_SHORT:
7913            if (depth > 1) {
7914            halveImage3D(cmpts,extractUshort,shoveUshort,
7915                         width,height,depth,
7916                         usersImage,dstImage,elementSize,groupSize,rowSize,
7917                         imageSize,myswapBytes);
7918            }
7919            else {
7920              halveImage_ushort(cmpts,width,height,usersImage,dstImage,
7921                                elementSize,rowSize,groupSize,myswapBytes);
7922            }
7923            break;
7924          case GL_SHORT:
7925            if (depth > 1) {
7926            halveImage3D(cmpts,extractSshort,shoveSshort,
7927                         width,height,depth,
7928                         usersImage,dstImage,elementSize,groupSize,rowSize,
7929                         imageSize,myswapBytes);
7930            }
7931            else {
7932              halveImage_short(cmpts,width,height,usersImage,dstImage,
7933                               elementSize,rowSize,groupSize,myswapBytes);
7934            }
7935            break;
7936          case GL_UNSIGNED_INT:
7937            if (depth > 1) {
7938            halveImage3D(cmpts,extractUint,shoveUint,
7939                         width,height,depth,
7940                         usersImage,dstImage,elementSize,groupSize,rowSize,
7941                         imageSize,myswapBytes);
7942            }
7943            else {
7944              halveImage_uint(cmpts,width,height,usersImage,dstImage,
7945                              elementSize,rowSize,groupSize,myswapBytes);
7946            }
7947            break;
7948          case GL_INT:
7949            if (depth > 1) {
7950            halveImage3D(cmpts,extractSint,shoveSint,
7951                         width,height,depth,
7952                         usersImage,dstImage,elementSize,groupSize,rowSize,
7953                         imageSize,myswapBytes);
7954            }
7955            else {
7956              halveImage_int(cmpts,width,height,usersImage,dstImage,
7957                             elementSize,rowSize,groupSize,myswapBytes);
7958            }
7959            break;
7960          case GL_FLOAT:
7961            if (depth > 1 ) {
7962            halveImage3D(cmpts,extractFloat,shoveFloat,
7963                         width,height,depth,
7964                         usersImage,dstImage,elementSize,groupSize,rowSize,
7965                         imageSize,myswapBytes);
7966            }
7967            else {
7968              halveImage_float(cmpts,width,height,usersImage,dstImage,
7969                               elementSize,rowSize,groupSize,myswapBytes);
7970            }
7971            break;
7972          case GL_UNSIGNED_BYTE_3_3_2:
7973            assert(format == GL_RGB);
7974            halveImagePackedPixel3D(3,extract332,shove332,
7975                                    width,height,depth,usersImage,dstImage,
7976                                    elementSize,rowSize,imageSize,myswapBytes);
7977            break;
7978          case GL_UNSIGNED_BYTE_2_3_3_REV:
7979            assert(format == GL_RGB);
7980            halveImagePackedPixel3D(3,extract233rev,shove233rev,
7981                                    width,height,depth,usersImage,dstImage,
7982                                    elementSize,rowSize,imageSize,myswapBytes);
7983            break;
7984          case GL_UNSIGNED_SHORT_5_6_5:
7985            halveImagePackedPixel3D(3,extract565,shove565,
7986                                    width,height,depth,usersImage,dstImage,
7987                                    elementSize,rowSize,imageSize,myswapBytes);
7988            break;
7989          case GL_UNSIGNED_SHORT_5_6_5_REV:
7990            halveImagePackedPixel3D(3,extract565rev,shove565rev,
7991                                    width,height,depth,usersImage,dstImage,
7992                                    elementSize,rowSize,imageSize,myswapBytes);
7993            break;
7994          case GL_UNSIGNED_SHORT_4_4_4_4:
7995            halveImagePackedPixel3D(4,extract4444,shove4444,
7996                                    width,height,depth,usersImage,dstImage,
7997                                    elementSize,rowSize,imageSize,myswapBytes);
7998            break;
7999          case GL_UNSIGNED_SHORT_4_4_4_4_REV:
8000            halveImagePackedPixel3D(4,extract4444rev,shove4444rev,
8001                                    width,height,depth,usersImage,dstImage,
8002                                    elementSize,rowSize,imageSize,myswapBytes);
8003            break;
8004          case GL_UNSIGNED_SHORT_5_5_5_1:
8005            halveImagePackedPixel3D(4,extract5551,shove5551,
8006                                    width,height,depth,usersImage,dstImage,
8007                                    elementSize,rowSize,imageSize,myswapBytes);
8008            break;
8009          case GL_UNSIGNED_SHORT_1_5_5_5_REV:
8010            halveImagePackedPixel3D(4,extract1555rev,shove1555rev,
8011                                    width,height,depth,usersImage,dstImage,
8012                                    elementSize,rowSize,imageSize,myswapBytes);
8013            break;
8014          case GL_UNSIGNED_INT_8_8_8_8:
8015            halveImagePackedPixel3D(4,extract8888,shove8888,
8016                                    width,height,depth,usersImage,dstImage,
8017                                    elementSize,rowSize,imageSize,myswapBytes);
8018            break;
8019          case GL_UNSIGNED_INT_8_8_8_8_REV:
8020            halveImagePackedPixel3D(4,extract8888rev,shove8888rev,
8021                                    width,height,depth,usersImage,dstImage,
8022                                    elementSize,rowSize,imageSize,myswapBytes);
8023            break;
8024          case GL_UNSIGNED_INT_10_10_10_2:
8025            halveImagePackedPixel3D(4,extract1010102,shove1010102,
8026                                    width,height,depth,usersImage,dstImage,
8027                                    elementSize,rowSize,imageSize,myswapBytes);
8028            break;
8029          case GL_UNSIGNED_INT_2_10_10_10_REV:
8030            halveImagePackedPixel3D(4,extract2101010rev,shove2101010rev,
8031                                    width,height,depth,usersImage,dstImage,
8032                                    elementSize,rowSize,imageSize,myswapBytes);
8033            break;
8034          default:
8035            assert(0);
8036            break;
8037          }
8038        newWidth = width/2;
8039        newHeight = height/2;
8040        newDepth = depth/2;
8041        /* clamp to 1 */
8042        if (newWidth < 1) newWidth= 1;
8043        if (newHeight < 1) newHeight= 1;
8044        if (newDepth < 1) newDepth= 1;
8045
8046        myswapBytes = 0;
8047        rowSize = newWidth * groupSize;
8048        imageSize= rowSize * newHeight; /* 3dstuff */
8049        memReq = imageSize3D(newWidth, newHeight, newDepth, format, type);
8050        /* Swap srcImage and dstImage */
8051        __GLU_SWAP_IMAGE(srcImage,dstImage);
8052        switch(type) {
8053        case GL_UNSIGNED_BYTE:
8054          dstImage = (GLubyte *)malloc(memReq);
8055          break;
8056        case GL_BYTE:
8057          dstImage = (GLbyte *)malloc(memReq);
8058          break;
8059        case GL_UNSIGNED_SHORT:
8060          dstImage = (GLushort *)malloc(memReq);
8061          break;
8062        case GL_SHORT:
8063          dstImage = (GLshort *)malloc(memReq);
8064          break;
8065        case GL_UNSIGNED_INT:
8066          dstImage = (GLuint *)malloc(memReq);
8067          break;
8068        case GL_INT:
8069          dstImage = (GLint *)malloc(memReq);
8070          break;
8071        case GL_FLOAT:
8072          dstImage = (GLfloat *)malloc(memReq);
8073          break;
8074        case GL_UNSIGNED_BYTE_3_3_2:
8075        case GL_UNSIGNED_BYTE_2_3_3_REV:
8076          dstImage = (GLubyte *)malloc(memReq);
8077          break;
8078        case GL_UNSIGNED_SHORT_5_6_5:
8079        case GL_UNSIGNED_SHORT_5_6_5_REV:
8080        case GL_UNSIGNED_SHORT_4_4_4_4:
8081        case GL_UNSIGNED_SHORT_4_4_4_4_REV:
8082        case GL_UNSIGNED_SHORT_5_5_5_1:
8083        case GL_UNSIGNED_SHORT_1_5_5_5_REV:
8084          dstImage = (GLushort *)malloc(memReq);
8085          break;
8086        case GL_UNSIGNED_INT_8_8_8_8:
8087        case GL_UNSIGNED_INT_8_8_8_8_REV:
8088        case GL_UNSIGNED_INT_10_10_10_2:
8089        case GL_UNSIGNED_INT_2_10_10_10_REV:
8090          dstImage = (GLuint *)malloc(memReq);
8091          break;
8092        default:
8093          return GLU_INVALID_ENUM; /* assertion */
8094        }
8095        if (dstImage == NULL) {
8096          glPixelStorei(GL_UNPACK_ALIGNMENT, psm.unpack_alignment);
8097          glPixelStorei(GL_UNPACK_SKIP_ROWS, psm.unpack_skip_rows);
8098          glPixelStorei(GL_UNPACK_SKIP_PIXELS, psm.unpack_skip_pixels);
8099          glPixelStorei(GL_UNPACK_ROW_LENGTH, psm.unpack_row_length);
8100          glPixelStorei(GL_UNPACK_SWAP_BYTES, psm.unpack_swap_bytes);
8101          glPixelStorei(GL_UNPACK_SKIP_IMAGES, psm.unpack_skip_images);
8102          glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, psm.unpack_image_height);
8103          free(srcImage);
8104          return GLU_OUT_OF_MEMORY;
8105        }
8106        /* level userLevel+1 is in srcImage; level userLevel already saved */
8107        level = userLevel+1;
8108    } else {/* user's image is *not* nice power-of-2 sized square */
8109        memReq = imageSize3D(newWidth, newHeight, newDepth, format, type);
8110        switch(type) {
8111            case GL_UNSIGNED_BYTE:
8112                dstImage = (GLubyte *)malloc(memReq);
8113                break;
8114            case GL_BYTE:
8115                dstImage = (GLbyte *)malloc(memReq);
8116                break;
8117            case GL_UNSIGNED_SHORT:
8118                dstImage = (GLushort *)malloc(memReq);
8119                break;
8120            case GL_SHORT:
8121                dstImage = (GLshort *)malloc(memReq);
8122                break;
8123            case GL_UNSIGNED_INT:
8124                dstImage = (GLuint *)malloc(memReq);
8125                break;
8126            case GL_INT:
8127                dstImage = (GLint *)malloc(memReq);
8128                break;
8129            case GL_FLOAT:
8130                dstImage = (GLfloat *)malloc(memReq);
8131                break;
8132            case GL_UNSIGNED_BYTE_3_3_2:
8133            case GL_UNSIGNED_BYTE_2_3_3_REV:
8134                dstImage = (GLubyte *)malloc(memReq);
8135                break;
8136            case GL_UNSIGNED_SHORT_5_6_5:
8137            case GL_UNSIGNED_SHORT_5_6_5_REV:
8138            case GL_UNSIGNED_SHORT_4_4_4_4:
8139            case GL_UNSIGNED_SHORT_4_4_4_4_REV:
8140            case GL_UNSIGNED_SHORT_5_5_5_1:
8141            case GL_UNSIGNED_SHORT_1_5_5_5_REV:
8142                dstImage = (GLushort *)malloc(memReq);
8143                break;
8144            case GL_UNSIGNED_INT_8_8_8_8:
8145            case GL_UNSIGNED_INT_8_8_8_8_REV:
8146            case GL_UNSIGNED_INT_10_10_10_2:
8147            case GL_UNSIGNED_INT_2_10_10_10_REV:
8148                dstImage = (GLuint *)malloc(memReq);
8149                break;
8150            default:
8151                return GLU_INVALID_ENUM; /* assertion */
8152        }
8153
8154        if (dstImage == NULL) {
8155            glPixelStorei(GL_UNPACK_ALIGNMENT, psm.unpack_alignment);
8156            glPixelStorei(GL_UNPACK_SKIP_ROWS, psm.unpack_skip_rows);
8157            glPixelStorei(GL_UNPACK_SKIP_PIXELS, psm.unpack_skip_pixels);
8158            glPixelStorei(GL_UNPACK_ROW_LENGTH, psm.unpack_row_length);
8159            glPixelStorei(GL_UNPACK_SWAP_BYTES, psm.unpack_swap_bytes);
8160            glPixelStorei(GL_UNPACK_SKIP_IMAGES, psm.unpack_skip_images);
8161            glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, psm.unpack_image_height);
8162            return GLU_OUT_OF_MEMORY;
8163        }
8164        /*printf("Build3DMipmaps(): ScaleImage3D %d %d %d->%d %d %d\n",
8165        width,height,depth,newWidth,newHeight,newDepth);*/
8166
8167        gluScaleImage3D(format, width, height, depth, type, usersImage,
8168                        newWidth, newHeight, newDepth, type, dstImage);
8169
8170        myswapBytes = 0;
8171        rowSize = newWidth * groupSize;
8172        imageSize = rowSize * newHeight; /* 3dstuff */
8173        /* Swap dstImage and srcImage */
8174        __GLU_SWAP_IMAGE(srcImage,dstImage);
8175
8176        if(levels != 0) { /* use as little memory as possible */
8177          {
8178             int nextWidth= newWidth/2;
8179             int nextHeight= newHeight/2;
8180             int nextDepth= newDepth/2;
8181             if (nextWidth < 1) nextWidth= 1;
8182             if (nextHeight < 1) nextHeight= 1;  
8183             if (nextDepth < 1) nextDepth= 1;    
8184
8185          memReq = imageSize3D(nextWidth, nextHeight, nextDepth, format, type);
8186          }
8187          switch(type) {
8188          case GL_UNSIGNED_BYTE:
8189            dstImage = (GLubyte *)malloc(memReq);
8190            break;
8191          case GL_BYTE:
8192            dstImage = (GLbyte *)malloc(memReq);
8193            break;
8194          case GL_UNSIGNED_SHORT:
8195            dstImage = (GLushort *)malloc(memReq);
8196            break;
8197          case GL_SHORT:
8198            dstImage = (GLshort *)malloc(memReq);
8199            break;
8200          case GL_UNSIGNED_INT:
8201            dstImage = (GLuint *)malloc(memReq);
8202            break;
8203          case GL_INT:
8204            dstImage = (GLint *)malloc(memReq);
8205            break;
8206          case GL_FLOAT:
8207            dstImage = (GLfloat *)malloc(memReq);
8208            break;
8209          case GL_UNSIGNED_BYTE_3_3_2:
8210          case GL_UNSIGNED_BYTE_2_3_3_REV:
8211            dstImage = (GLubyte *)malloc(memReq);
8212            break;
8213          case GL_UNSIGNED_SHORT_5_6_5:
8214          case GL_UNSIGNED_SHORT_5_6_5_REV:
8215          case GL_UNSIGNED_SHORT_4_4_4_4:
8216          case GL_UNSIGNED_SHORT_4_4_4_4_REV:
8217          case GL_UNSIGNED_SHORT_5_5_5_1:
8218          case GL_UNSIGNED_SHORT_1_5_5_5_REV:
8219            dstImage = (GLushort *)malloc(memReq);
8220            break;
8221          case GL_UNSIGNED_INT_8_8_8_8:
8222          case GL_UNSIGNED_INT_8_8_8_8_REV:
8223          case GL_UNSIGNED_INT_10_10_10_2:
8224          case GL_UNSIGNED_INT_2_10_10_10_REV:
8225            dstImage = (GLuint *)malloc(memReq);
8226            break;
8227          default:
8228            return GLU_INVALID_ENUM; /* assertion */
8229          }
8230          if (dstImage == NULL) {
8231            glPixelStorei(GL_UNPACK_ALIGNMENT, psm.unpack_alignment);
8232            glPixelStorei(GL_UNPACK_SKIP_ROWS, psm.unpack_skip_rows);
8233            glPixelStorei(GL_UNPACK_SKIP_PIXELS, psm.unpack_skip_pixels);
8234            glPixelStorei(GL_UNPACK_ROW_LENGTH, psm.unpack_row_length);
8235            glPixelStorei(GL_UNPACK_SWAP_BYTES, psm.unpack_swap_bytes);
8236            glPixelStorei(GL_UNPACK_SKIP_IMAGES, psm.unpack_skip_images);
8237            glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, psm.unpack_image_height);
8238            free(srcImage);
8239            return GLU_OUT_OF_MEMORY;
8240          }
8241        }
8242        /* level userLevel is in srcImage; nothing saved yet */
8243        level = userLevel;       
8244    }
8245
8246    glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE);
8247    if (baseLevel <= level && level <= maxLevel) {
8248      gluTexImage3D(target, level, internalFormat, newWidth, newHeight, newDepth,
8249                   0,format, type, (void *)srcImage);
8250    }
8251    level++; /* update current level for the loop */
8252    for (; level <= levels; level++) {
8253        switch(type) {
8254            case GL_UNSIGNED_BYTE:
8255                if (newDepth > 1) {
8256                halveImage3D(cmpts,extractUbyte,shoveUbyte,
8257                             newWidth,newHeight,newDepth,
8258                             srcImage,dstImage,elementSize,groupSize,rowSize,
8259                             imageSize,myswapBytes);
8260                }
8261                else {
8262                  halveImage_ubyte(cmpts,newWidth,newHeight,srcImage,dstImage,
8263                                   elementSize,rowSize,groupSize);
8264                }
8265                break;
8266            case GL_BYTE:
8267                if (newDepth > 1) {
8268                halveImage3D(cmpts,extractSbyte,shoveSbyte,
8269                             newWidth,newHeight,newDepth,
8270                             srcImage,dstImage,elementSize,groupSize,rowSize,
8271                             imageSize,myswapBytes);
8272                }
8273                else {
8274                  halveImage_byte(cmpts,newWidth,newHeight,srcImage,dstImage,
8275                                   elementSize,rowSize,groupSize);
8276                }
8277                break;
8278            case GL_UNSIGNED_SHORT:
8279                if (newDepth > 1) {
8280                halveImage3D(cmpts,extractUshort,shoveUshort,
8281                             newWidth,newHeight,newDepth,
8282                             srcImage,dstImage,elementSize,groupSize,rowSize,
8283                             imageSize,myswapBytes);
8284                }
8285                else {
8286                  halveImage_ushort(cmpts,newWidth,newHeight,srcImage,dstImage,
8287                                    elementSize,rowSize,groupSize,myswapBytes);
8288                }
8289                break;
8290            case GL_SHORT:
8291                if (newDepth > 1) {
8292                halveImage3D(cmpts,extractSshort,shoveSshort,
8293                             newWidth,newHeight,newDepth,
8294                             srcImage,dstImage,elementSize,groupSize,rowSize,
8295                             imageSize,myswapBytes);
8296                }
8297                else {
8298                  halveImage_short(cmpts,newWidth,newHeight,srcImage,dstImage,
8299                                   elementSize,rowSize,groupSize,myswapBytes);
8300                }
8301                break;
8302            case GL_UNSIGNED_INT:
8303                if (newDepth > 1) {
8304                halveImage3D(cmpts,extractUint,shoveUint,
8305                             newWidth,newHeight,newDepth,
8306                             srcImage,dstImage,elementSize,groupSize,rowSize,
8307                             imageSize,myswapBytes);
8308                }
8309                else {
8310                  halveImage_uint(cmpts,newWidth,newHeight,srcImage,dstImage,
8311                                  elementSize,rowSize,groupSize,myswapBytes);
8312                }
8313                break;
8314            case GL_INT:
8315                if (newDepth > 1) {
8316                halveImage3D(cmpts,extractSint,shoveSint,
8317                             newWidth,newHeight,newDepth,
8318                             srcImage,dstImage,elementSize,groupSize,rowSize,
8319                             imageSize,myswapBytes);
8320                }
8321                else {
8322                  halveImage_int(cmpts,newWidth,newHeight,srcImage,dstImage,
8323                                 elementSize,rowSize,groupSize,myswapBytes);
8324                }
8325                break;
8326            case GL_FLOAT:
8327                if (newDepth > 1) {
8328                halveImage3D(cmpts,extractFloat,shoveFloat,
8329                             newWidth,newHeight,newDepth,
8330                             srcImage,dstImage,elementSize,groupSize,rowSize,
8331                             imageSize,myswapBytes);
8332                }
8333                else {
8334                  halveImage_float(cmpts,newWidth,newHeight,srcImage,dstImage,
8335                                   elementSize,rowSize,groupSize,myswapBytes);
8336                }
8337                break;
8338            case GL_UNSIGNED_BYTE_3_3_2:
8339                halveImagePackedPixel3D(3,extract332,shove332,
8340                                        newWidth,newHeight,newDepth,
8341                                        srcImage,dstImage,elementSize,rowSize,
8342                                        imageSize,myswapBytes);
8343                break;
8344            case GL_UNSIGNED_BYTE_2_3_3_REV:
8345                halveImagePackedPixel3D(3,extract233rev,shove233rev,
8346                                        newWidth,newHeight,newDepth,
8347                                        srcImage,dstImage,elementSize,rowSize,
8348                                        imageSize,myswapBytes);
8349                break;
8350            case GL_UNSIGNED_SHORT_5_6_5:
8351                halveImagePackedPixel3D(3,extract565,shove565,
8352                                        newWidth,newHeight,newDepth,
8353                                        srcImage,dstImage,elementSize,rowSize,
8354                                        imageSize,myswapBytes);
8355                break;
8356            case GL_UNSIGNED_SHORT_5_6_5_REV:
8357                halveImagePackedPixel3D(3,extract565rev,shove565rev,
8358                                        newWidth,newHeight,newDepth,
8359                                        srcImage,dstImage,elementSize,rowSize,
8360                                        imageSize,myswapBytes);
8361                break;
8362            case GL_UNSIGNED_SHORT_4_4_4_4:
8363                halveImagePackedPixel3D(4,extract4444,shove4444,
8364                                        newWidth,newHeight,newDepth,
8365                                        srcImage,dstImage,elementSize,rowSize,
8366                                        imageSize,myswapBytes);
8367                break;
8368            case GL_UNSIGNED_SHORT_4_4_4_4_REV:
8369                halveImagePackedPixel3D(4,extract4444rev,shove4444rev,
8370                                        newWidth,newHeight,newDepth,
8371                                        srcImage,dstImage,elementSize,rowSize,
8372                                        imageSize,myswapBytes);
8373                break;
8374            case GL_UNSIGNED_SHORT_5_5_5_1:              
8375                halveImagePackedPixel3D(4,extract5551,shove5551,
8376                                        newWidth,newHeight,newDepth,
8377                                        srcImage,dstImage,elementSize,rowSize,
8378                                        imageSize,myswapBytes);
8379                break;
8380            case GL_UNSIGNED_SHORT_1_5_5_5_REV:          
8381                halveImagePackedPixel3D(4,extract1555rev,shove1555rev,
8382                                        newWidth,newHeight,newDepth,
8383                                        srcImage,dstImage,elementSize,rowSize,
8384                                        imageSize,myswapBytes);
8385                break;
8386            case GL_UNSIGNED_INT_8_8_8_8:
8387                halveImagePackedPixel3D(4,extract8888,shove8888,
8388                                        newWidth,newHeight,newDepth,
8389                                        srcImage,dstImage,elementSize,rowSize,
8390                                        imageSize,myswapBytes);
8391                break;
8392            case GL_UNSIGNED_INT_8_8_8_8_REV:
8393                halveImagePackedPixel3D(4,extract8888rev,shove8888rev,
8394                                        newWidth,newHeight,newDepth,
8395                                        srcImage,dstImage,elementSize,rowSize,
8396                                        imageSize,myswapBytes);
8397                break;
8398            case GL_UNSIGNED_INT_10_10_10_2:
8399                halveImagePackedPixel3D(4,extract1010102,shove1010102,
8400                                        newWidth,newHeight,newDepth,
8401                                        srcImage,dstImage,elementSize,rowSize,
8402                                        imageSize,myswapBytes);
8403                break;
8404            case GL_UNSIGNED_INT_2_10_10_10_REV:
8405                halveImagePackedPixel3D(4,extract2101010rev,shove2101010rev,
8406                                        newWidth,newHeight,newDepth,
8407                                        srcImage,dstImage,elementSize,rowSize,
8408                                        imageSize,myswapBytes);
8409                break;
8410            default:
8411                assert(0);
8412                break;
8413        }
8414
8415        __GLU_SWAP_IMAGE(srcImage,dstImage);
8416
8417        if (newWidth > 1) { newWidth /= 2; rowSize /= 2;}
8418        if (newHeight > 1) { newHeight /= 2; imageSize = rowSize * newHeight; }
8419        if (newDepth > 1) newDepth /= 2;
8420        {
8421           /* call tex image with srcImage untouched since it's not padded */
8422           if (baseLevel <= level && level <= maxLevel) {
8423             gluTexImage3D(target, level, internalFormat, newWidth, newHeight,
8424                          newDepth,0, format, type, (void *) srcImage);
8425           }
8426        }
8427    } /* for level */
8428    glPixelStorei(GL_UNPACK_ALIGNMENT, psm.unpack_alignment);
8429    glPixelStorei(GL_UNPACK_SKIP_ROWS, psm.unpack_skip_rows);
8430    glPixelStorei(GL_UNPACK_SKIP_PIXELS, psm.unpack_skip_pixels);
8431    glPixelStorei(GL_UNPACK_ROW_LENGTH, psm.unpack_row_length);
8432    glPixelStorei(GL_UNPACK_SWAP_BYTES, psm.unpack_swap_bytes);
8433    glPixelStorei(GL_UNPACK_SKIP_IMAGES, psm.unpack_skip_images);
8434    glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, psm.unpack_image_height);
8435
8436    free(srcImage); /*if you get to here, a srcImage has always been malloc'ed*/
8437    if (dstImage) { /* if it's non-rectangular and only 1 level */
8438      free(dstImage);
8439    }
8440    return 0;
8441 } /* gluBuild3DMipmapLevelsCore() */
8442
8443 GLint GLAPIENTRY
8444 gluBuild3DMipmapLevels(GLenum target, GLint internalFormat,
8445                              GLsizei width, GLsizei height, GLsizei depth,
8446                              GLenum format, GLenum type,
8447                              GLint userLevel, GLint baseLevel, GLint maxLevel,
8448                              const void *data)
8449 {
8450    int level, levels;
8451
8452    int rc= checkMipmapArgs(internalFormat,format,type);
8453    if (rc != 0) return rc;
8454
8455    if (width < 1 || height < 1 || depth < 1) {
8456        return GLU_INVALID_VALUE;
8457    }
8458
8459    if(type == GL_BITMAP) {
8460       return GLU_INVALID_ENUM;
8461    }
8462
8463    levels = computeLog(width);
8464    level = computeLog(height);
8465    if (level > levels) levels=level;
8466    level = computeLog(depth);
8467    if (level > levels) levels=level;
8468
8469    levels+= userLevel;
8470    if (!isLegalLevels(userLevel,baseLevel,maxLevel,levels))
8471       return GLU_INVALID_VALUE;
8472
8473    return gluBuild3DMipmapLevelsCore(target, internalFormat,
8474                                      width, height, depth,
8475                                      width, height, depth,
8476                                      format, type,
8477                                      userLevel, baseLevel, maxLevel,
8478                                      data);
8479 } /* gluBuild3DMipmapLevels() */
8480
8481 GLint GLAPIENTRY
8482 gluBuild3DMipmaps(GLenum target, GLint internalFormat,
8483                         GLsizei width, GLsizei height, GLsizei depth,
8484                         GLenum format, GLenum type, const void *data)
8485 {
8486    GLint widthPowerOf2, heightPowerOf2, depthPowerOf2;
8487    int level, levels;
8488
8489    int rc= checkMipmapArgs(internalFormat,format,type);
8490    if (rc != 0) return rc;
8491
8492    if (width < 1 || height < 1 || depth < 1) {
8493        return GLU_INVALID_VALUE;
8494    }
8495
8496    if(type == GL_BITMAP) {
8497       return GLU_INVALID_ENUM;
8498    }
8499
8500    closestFit3D(target,width,height,depth,internalFormat,format,type,
8501                 &widthPowerOf2,&heightPowerOf2,&depthPowerOf2);
8502
8503    levels = computeLog(widthPowerOf2);
8504    level = computeLog(heightPowerOf2);
8505    if (level > levels) levels=level;
8506    level = computeLog(depthPowerOf2);
8507    if (level > levels) levels=level;
8508
8509    return gluBuild3DMipmapLevelsCore(target, internalFormat,
8510                                      width, height, depth,
8511                                      widthPowerOf2, heightPowerOf2,
8512                                      depthPowerOf2,
8513                                      format, type, 0, 0, levels,
8514                                      data);
8515 } /* gluBuild3DMipmaps() */
8516
8517 static GLdouble extractUbyte(int isSwap, const void *ubyte)
8518 {
8519    isSwap= isSwap;              /* turn off warnings */
8520
8521    assert(*((const GLubyte *)ubyte) <= 255);
8522
8523    return (GLdouble)(*((const GLubyte *)ubyte));
8524 } /* extractUbyte() */
8525
8526 static void shoveUbyte(GLdouble value, int index, void *data)
8527 {
8528    assert(0.0 <= value && value < 256.0);
8529
8530    ((GLubyte *)data)[index]= (GLubyte)value;
8531 } /* shoveUbyte() */
8532
8533 static GLdouble extractSbyte(int isSwap, const void *sbyte)
8534 {
8535    isSwap= isSwap;              /* turn off warnings */
8536
8537    assert(*((const GLbyte *)sbyte) <= 127);
8538
8539    return (GLdouble)(*((const GLbyte *)sbyte));
8540 } /* extractSbyte() */
8541
8542 static void shoveSbyte(GLdouble value, int index, void *data)
8543 {
8544    ((GLbyte *)data)[index]= (GLbyte)value;
8545 } /* shoveSbyte() */
8546
8547 static GLdouble extractUshort(int isSwap, const void *uitem)
8548 {
8549    GLushort ushort;
8550
8551    if (isSwap) {
8552      ushort= __GLU_SWAP_2_BYTES(uitem);
8553    }
8554    else {
8555      ushort= *(const GLushort *)uitem;
8556    }
8557
8558    assert(ushort <= 65535);
8559
8560    return (GLdouble)ushort;
8561 } /* extractUshort() */
8562
8563 static void shoveUshort(GLdouble value, int index, void *data)
8564 {
8565    assert(0.0 <= value && value < 65536.0);
8566
8567    ((GLushort *)data)[index]= (GLushort)value;
8568 } /* shoveUshort() */
8569
8570 static GLdouble extractSshort(int isSwap, const void *sitem)
8571 {
8572    GLshort sshort;
8573
8574    if (isSwap) {
8575      sshort= __GLU_SWAP_2_BYTES(sitem);
8576    }
8577    else {
8578      sshort= *(const GLshort *)sitem;
8579    }
8580
8581    assert(sshort <= 32767);
8582
8583    return (GLdouble)sshort;
8584 } /* extractSshort() */
8585
8586 static void shoveSshort(GLdouble value, int index, void *data)
8587 {
8588    assert(0.0 <= value && value < 32768.0);
8589
8590    ((GLshort *)data)[index]= (GLshort)value;
8591 } /* shoveSshort() */
8592
8593 static GLdouble extractUint(int isSwap, const void *uitem)
8594 {
8595    GLuint uint;
8596
8597    if (isSwap) {
8598      uint= __GLU_SWAP_4_BYTES(uitem);
8599    }
8600    else {
8601      uint= *(const GLuint *)uitem;
8602    }
8603
8604    assert(uint <= 0xffffffff);
8605
8606    return (GLdouble)uint;
8607 } /* extractUint() */
8608
8609 static void shoveUint(GLdouble value, int index, void *data)
8610 {
8611    assert(0.0 <= value && value <= (GLdouble) UINT_MAX);
8612
8613    ((GLuint *)data)[index]= (GLuint)value;
8614 } /* shoveUint() */
8615
8616 static GLdouble extractSint(int isSwap, const void *sitem)
8617 {
8618    GLint sint;
8619
8620    if (isSwap) {
8621      sint= __GLU_SWAP_4_BYTES(sitem);
8622    }
8623    else {
8624      sint= *(const GLint *)sitem;
8625    }
8626
8627    assert(sint <= 0x7fffffff);
8628
8629    return (GLdouble)sint;
8630 } /* extractSint() */
8631
8632 static void shoveSint(GLdouble value, int index, void *data)
8633 {
8634    assert(0.0 <= value && value <= (GLdouble) INT_MAX);
8635
8636    ((GLint *)data)[index]= (GLint)value;
8637 } /* shoveSint() */
8638
8639 static GLdouble extractFloat(int isSwap, const void *item)
8640 {
8641    GLfloat ffloat;
8642
8643    if (isSwap) {
8644      ffloat= __GLU_SWAP_4_BYTES(item);
8645    }
8646    else {
8647      ffloat= *(const GLfloat *)item;
8648    }
8649
8650    assert(ffloat <= 1.0);
8651
8652    return (GLdouble)ffloat;
8653 } /* extractFloat() */
8654
8655 static void shoveFloat(GLdouble value, int index, void *data)
8656 {
8657    assert(0.0 <= value && value <= 1.0);
8658
8659    ((GLfloat *)data)[index]= value;
8660 } /* shoveFloat() */
8661
8662 static void halveImageSlice(int components,
8663                             GLdouble (*extract)(int, const void *),
8664                             void (*shove)(GLdouble, int, void *),
8665                             GLint width, GLint height, GLint depth,
8666                             const void *dataIn, void *dataOut,
8667                             GLint elementSizeInBytes,
8668                             GLint groupSizeInBytes,
8669                             GLint rowSizeInBytes,
8670                             GLint imageSizeInBytes,
8671                             GLint isSwap)
8672 {
8673    int ii, jj;
8674    int halfWidth= width / 2;
8675    int halfHeight= height / 2;
8676    int halfDepth= depth / 2;
8677    const char *src= (const char *)dataIn;
8678    int rowPadBytes= rowSizeInBytes - (width * groupSizeInBytes);
8679    int imagePadBytes= imageSizeInBytes - (width*height*groupSizeInBytes);
8680    int outIndex= 0;
8681
8682    assert((width == 1 || height == 1) && depth >= 2);
8683
8684    if (width == height) {       /* a 1-pixel column viewed from top */
8685       /* printf("1-column\n");*/
8686       assert(width == 1 && height == 1);
8687       assert(depth >= 2);
8688
8689       for (ii= 0; ii< halfDepth; ii++) {
8690          int cc;
8691
8692          for (cc = 0; cc < components; cc++) {
8693             double totals[4];
8694             double extractTotals[BOX2][4];
8695             int kk;
8696
8697             extractTotals[0][cc]= (*extract)(isSwap,src);
8698             extractTotals[1][cc]= (*extract)(isSwap,(src+imageSizeInBytes));
8699
8700             /* average 2 pixels since only a column */
8701             totals[cc]= 0.0;
8702             /* totals[RED]= extractTotals[0][RED]+extractTotals[1][RED];
8703              * totals[RED]/= 2.0;
8704              */
8705             for (kk = 0; kk < BOX2; kk++) {
8706               totals[cc]+= extractTotals[kk][cc];
8707             }
8708             totals[cc]/= (double)BOX2;
8709
8710             (*shove)(totals[cc],outIndex,dataOut);
8711             outIndex++;
8712             src+= elementSizeInBytes;
8713          } /* for cc */
8714
8715          /* skip over to next group of 2 */
8716          src+= rowSizeInBytes;
8717       } /* for ii */
8718
8719       assert(src == &((const char *)dataIn)[rowSizeInBytes*height*depth]);
8720       assert(outIndex == halfDepth * components);
8721    }
8722    else if (height == 1) {      /* horizontal slice viewed from top */
8723       /* printf("horizontal slice\n"); */
8724       assert(width != 1);
8725
8726       for (ii= 0; ii< halfDepth; ii++) {
8727          for (jj= 0; jj< halfWidth; jj++) {
8728             int cc;
8729
8730             for (cc = 0; cc < components; cc++) {
8731                int kk;
8732                double totals[4];
8733                double extractTotals[BOX4][4];
8734
8735                extractTotals[0][cc]=(*extract)(isSwap,src);
8736                extractTotals[1][cc]=(*extract)(isSwap,
8737                                                (src+groupSizeInBytes));
8738                extractTotals[2][cc]=(*extract)(isSwap,
8739                                                (src+imageSizeInBytes));
8740                extractTotals[3][cc]=(*extract)(isSwap,
8741                                                (src+imageSizeInBytes+groupSizeInBytes));
8742
8743                /* grab 4 pixels to average */
8744                totals[cc]= 0.0;
8745                /* totals[RED]= extractTotals[0][RED]+extractTotals[1][RED]+
8746                 *              extractTotals[2][RED]+extractTotals[3][RED];
8747                 * totals[RED]/= 4.0;
8748                 */
8749                for (kk = 0; kk < BOX4; kk++) {
8750                   totals[cc]+= extractTotals[kk][cc];
8751                }
8752                totals[cc]/= (double)BOX4;
8753
8754                (*shove)(totals[cc],outIndex,dataOut);
8755                outIndex++;
8756
8757                src+= elementSizeInBytes;
8758             } /* for cc */
8759
8760             /* skip over to next horizontal square of 4 */
8761             src+= groupSizeInBytes;
8762          } /* for jj */
8763          src+= rowPadBytes;
8764
8765          src+= rowSizeInBytes;
8766       } /* for ii */
8767
8768       assert(src == &((const char *)dataIn)[rowSizeInBytes*height*depth]);
8769       assert(outIndex == halfWidth * halfDepth * components);
8770    }
8771    else if (width == 1) {       /* vertical slice viewed from top */
8772       /* printf("vertical slice\n"); */
8773       assert(height != 1);
8774
8775       for (ii= 0; ii< halfDepth; ii++) {
8776          for (jj= 0; jj< halfHeight; jj++) {
8777             int cc;
8778
8779             for (cc = 0; cc < components; cc++) {
8780                int kk;
8781                double totals[4];
8782                double extractTotals[BOX4][4];
8783
8784                extractTotals[0][cc]=(*extract)(isSwap,src);
8785                extractTotals[1][cc]=(*extract)(isSwap,
8786                                                (src+rowSizeInBytes));
8787                extractTotals[2][cc]=(*extract)(isSwap,
8788                                                (src+imageSizeInBytes));
8789                extractTotals[3][cc]=(*extract)(isSwap,
8790                                                (src+imageSizeInBytes+rowSizeInBytes));
8791
8792                /* grab 4 pixels to average */
8793                totals[cc]= 0.0;
8794                /* totals[RED]= extractTotals[0][RED]+extractTotals[1][RED]+
8795                 *              extractTotals[2][RED]+extractTotals[3][RED];
8796                 * totals[RED]/= 4.0;
8797                 */
8798                for (kk = 0; kk < BOX4; kk++) {
8799                   totals[cc]+= extractTotals[kk][cc];
8800                }
8801                totals[cc]/= (double)BOX4;
8802
8803                (*shove)(totals[cc],outIndex,dataOut);
8804                outIndex++;
8805
8806                src+= elementSizeInBytes;
8807             } /* for cc */
8808             src+= rowPadBytes;
8809
8810             /* skip over to next vertical square of 4 */
8811             src+= rowSizeInBytes;
8812          } /* for jj */
8813          src+= imagePadBytes;
8814
8815          src+= imageSizeInBytes;
8816       } /* for ii */
8817
8818       assert(src == &((const char *)dataIn)[rowSizeInBytes*height*depth]);
8819       assert(outIndex == halfHeight * halfDepth * components);
8820    }
8821
8822 } /* halveImageSlice() */
8823
8824 static void halveImage3D(int components,
8825                          GLdouble (*extract)(int, const void *),
8826                          void (*shove)(GLdouble, int, void *),
8827                          GLint width, GLint height, GLint depth,
8828                          const void *dataIn, void *dataOut,
8829                          GLint elementSizeInBytes,
8830                          GLint groupSizeInBytes,
8831                          GLint rowSizeInBytes,
8832                          GLint imageSizeInBytes,
8833                          GLint isSwap)
8834 {
8835    assert(depth > 1);
8836
8837    /* a horizontal/vertical/one-column slice viewed from top */
8838    if (width == 1 || height == 1) {
8839       assert(1 <= depth);
8840
8841       halveImageSlice(components,extract,shove, width, height, depth,
8842                       dataIn, dataOut, elementSizeInBytes, groupSizeInBytes,
8843                       rowSizeInBytes, imageSizeInBytes, isSwap);
8844       return;
8845    }
8846    {
8847       int ii, jj, dd;
8848
8849       int halfWidth= width / 2;
8850       int halfHeight= height / 2;
8851       int halfDepth= depth / 2;
8852       const char *src= (const char *) dataIn;
8853       int rowPadBytes= rowSizeInBytes - (width*groupSizeInBytes);
8854       int imagePadBytes= imageSizeInBytes - (width*height*groupSizeInBytes);
8855       int outIndex= 0;
8856
8857       for (dd= 0; dd < halfDepth; dd++) {
8858          for (ii= 0; ii< halfHeight; ii++) {
8859             for (jj= 0; jj< halfWidth; jj++) {
8860                int cc;
8861
8862                for (cc= 0; cc < components; cc++) {
8863                   int kk;
8864 #define BOX8 8
8865                   double totals[4];     /* 4 is maximum components */
8866                   double extractTotals[BOX8][4]; /* 4 is maximum components */
8867
8868                   extractTotals[0][cc]= (*extract)(isSwap,src);
8869                   extractTotals[1][cc]= (*extract)(isSwap,
8870                                                    (src+groupSizeInBytes));
8871                   extractTotals[2][cc]= (*extract)(isSwap,
8872                                                    (src+rowSizeInBytes));
8873                   extractTotals[3][cc]= (*extract)(isSwap,
8874                                                    (src+rowSizeInBytes+groupSizeInBytes));
8875
8876                   extractTotals[4][cc]= (*extract)(isSwap,
8877                                                    (src+imageSizeInBytes));
8878
8879                   extractTotals[5][cc]= (*extract)(isSwap,
8880                                                    (src+groupSizeInBytes+imageSizeInBytes));
8881                   extractTotals[6][cc]= (*extract)(isSwap,
8882                                                    (src+rowSizeInBytes+imageSizeInBytes));
8883                   extractTotals[7][cc]= (*extract)(isSwap,
8884                                                    (src+rowSizeInBytes+groupSizeInBytes+imageSizeInBytes));
8885
8886                   totals[cc]= 0.0;
8887
8888                   /* totals[RED]= extractTotals[0][RED]+extractTotals[1][RED]+
8889                    *              extractTotals[2][RED]+extractTotals[3][RED]+
8890                    *              extractTotals[4][RED]+extractTotals[5][RED]+
8891                    *              extractTotals[6][RED]+extractTotals[7][RED];
8892                    * totals[RED]/= 8.0;
8893                    */
8894                   for (kk = 0; kk < BOX8; kk++) {
8895                      totals[cc]+= extractTotals[kk][cc];
8896                   }
8897                   totals[cc]/= (double)BOX8;
8898
8899                   (*shove)(totals[cc],outIndex,dataOut);
8900
8901                   outIndex++;
8902
8903                   src+= elementSizeInBytes; /* go to next component */
8904                } /* for cc */
8905
8906                /* skip over to next square of 4 */
8907                src+= groupSizeInBytes;
8908             } /* for jj */
8909             /* skip past pad bytes, if any, to get to next row */
8910             src+= rowPadBytes;
8911
8912             /* src is at beginning of a row here, but it's the second row of
8913              * the square block of 4 pixels that we just worked on so we
8914              * need to go one more row.
8915              * i.e.,
8916              *                   OO...
8917              *           here -->OO...
8918              *       but want -->OO...
8919              *                   OO...
8920              *                   ...
8921              */
8922             src+= rowSizeInBytes;
8923          } /* for ii */
8924
8925          /* skip past pad bytes, if any, to get to next image */
8926          src+= imagePadBytes;
8927
8928          src+= imageSizeInBytes;
8929       } /* for dd */
8930
8931       /* both pointers must reach one byte after the end */
8932       assert(src == &((const char *)dataIn)[rowSizeInBytes*height*depth]);
8933       assert(outIndex == halfWidth * halfHeight * halfDepth * components);
8934    }
8935 } /* halveImage3D() */
8936
8937
8938
8939 /*** mipmap.c ***/
8940