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