Tizen 2.0 Release
[profile/ivi/osmesa.git] / src / glu / sgi / libutil / mipmap.c
1 /*
2  * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
3  * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a
6  * copy of this software and associated documentation files (the "Software"),
7  * to deal in the Software without restriction, including without limitation
8  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9  * and/or sell copies of the Software, and to permit persons to whom the
10  * Software is furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice including the dates of first publication and
13  * either this permission notice or a reference to
14  * http://oss.sgi.com/projects/FreeB/
15  * shall be included in all copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20  * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
22  * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23  * SOFTWARE.
24  *
25  * Except as contained in this notice, the name of Silicon Graphics, Inc.
26  * shall not be used in advertising or otherwise to promote the sale, use or
27  * other dealings in this Software without prior written authorization from
28  * Silicon Graphics, Inc.
29  */
30
31 #include "gluos.h"
32 #include <assert.h>
33 #include <GL/glu.h>
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37 #include <limits.h>             /* UINT_MAX */
38 #include <math.h>
39
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         free(beforeImage);
3529         free(afterImage);
3530         return GLU_OUT_OF_MEMORY;
3531     }
3532
3533     retrieveStoreModes(&psm);
3534     fill_image(&psm,widthin, heightin, format, typein, is_index(format),
3535             datain, beforeImage);
3536     components = elements_per_group(format, 0);
3537     scale_internal(components, widthin, heightin, beforeImage,
3538             widthout, heightout, afterImage);
3539     empty_image(&psm,widthout, heightout, format, typeout,
3540             is_index(format), afterImage, dataout);
3541     free((GLbyte *) beforeImage);
3542     free((GLbyte *) afterImage);
3543
3544     return 0;
3545 }
3546
3547 int gluBuild1DMipmapLevelsCore(GLenum target, GLint internalFormat,
3548                                GLsizei width,
3549                                GLsizei widthPowerOf2,
3550                                GLenum format, GLenum type,
3551                                GLint userLevel, GLint baseLevel,GLint maxLevel,
3552                                const void *data)
3553 {
3554     GLint newwidth;
3555     GLint level, levels;
3556     GLushort *newImage;
3557     GLint newImage_width;
3558     GLushort *otherImage;
3559     GLushort *imageTemp;
3560     GLint memreq;
3561     GLint cmpts;
3562     PixelStorageModes psm;
3563
3564     assert(checkMipmapArgs(internalFormat,format,type) == 0);
3565     assert(width >= 1);
3566
3567     otherImage = NULL;
3568
3569     newwidth= widthPowerOf2;
3570     levels = computeLog(newwidth);
3571
3572     levels+= userLevel;
3573
3574     retrieveStoreModes(&psm);
3575     newImage = (GLushort *)
3576         malloc(image_size(width, 1, format, GL_UNSIGNED_SHORT));
3577     newImage_width = width;
3578     if (newImage == NULL) {
3579         return GLU_OUT_OF_MEMORY;
3580     }
3581     fill_image(&psm,width, 1, format, type, is_index(format),
3582             data, newImage);
3583     cmpts = elements_per_group(format,type);
3584     glPixelStorei(GL_UNPACK_ALIGNMENT, 2);
3585     glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
3586     glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
3587     glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
3588     /*
3589     ** If swap_bytes was set, swapping occurred in fill_image.
3590     */
3591     glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE);
3592
3593     for (level = userLevel; level <= levels; level++) {
3594         if (newImage_width == newwidth) {
3595             /* Use newImage for this level */
3596             if (baseLevel <= level && level <= maxLevel) {
3597             glTexImage1D(target, level, internalFormat, newImage_width,
3598                     0, format, GL_UNSIGNED_SHORT, (void *) newImage);
3599             }
3600         } else {
3601             if (otherImage == NULL) {
3602                 memreq = image_size(newwidth, 1, format, GL_UNSIGNED_SHORT);
3603                 otherImage = (GLushort *) malloc(memreq);
3604                 if (otherImage == NULL) {
3605                     glPixelStorei(GL_UNPACK_ALIGNMENT, psm.unpack_alignment);
3606                     glPixelStorei(GL_UNPACK_SKIP_ROWS, psm.unpack_skip_rows);
3607                     glPixelStorei(GL_UNPACK_SKIP_PIXELS,psm.unpack_skip_pixels);
3608                     glPixelStorei(GL_UNPACK_ROW_LENGTH, psm.unpack_row_length);
3609                     glPixelStorei(GL_UNPACK_SWAP_BYTES, psm.unpack_swap_bytes);
3610                     free(newImage);
3611                     return GLU_OUT_OF_MEMORY;
3612                 }
3613             }
3614             scale_internal(cmpts, newImage_width, 1, newImage,
3615                     newwidth, 1, otherImage);
3616             /* Swap newImage and otherImage */
3617             imageTemp = otherImage;
3618             otherImage = newImage;
3619             newImage = imageTemp;
3620
3621             newImage_width = newwidth;
3622             if (baseLevel <= level && level <= maxLevel) {
3623             glTexImage1D(target, level, internalFormat, newImage_width,
3624                     0, format, GL_UNSIGNED_SHORT, (void *) newImage);
3625             }
3626         }
3627         if (newwidth > 1) newwidth /= 2;
3628     }
3629     glPixelStorei(GL_UNPACK_ALIGNMENT, psm.unpack_alignment);
3630     glPixelStorei(GL_UNPACK_SKIP_ROWS, psm.unpack_skip_rows);
3631     glPixelStorei(GL_UNPACK_SKIP_PIXELS, psm.unpack_skip_pixels);
3632     glPixelStorei(GL_UNPACK_ROW_LENGTH, psm.unpack_row_length);
3633     glPixelStorei(GL_UNPACK_SWAP_BYTES, psm.unpack_swap_bytes);
3634
3635     free((GLbyte *) newImage);
3636     if (otherImage) {
3637         free((GLbyte *) otherImage);
3638     }
3639     return 0;
3640 }
3641
3642 GLint GLAPIENTRY
3643 gluBuild1DMipmapLevels(GLenum target, GLint internalFormat,
3644                              GLsizei width,
3645                              GLenum format, GLenum type,
3646                              GLint userLevel, GLint baseLevel, GLint maxLevel,
3647                              const void *data)
3648 {
3649    int levels;
3650
3651    int rc= checkMipmapArgs(internalFormat,format,type);
3652    if (rc != 0) return rc;
3653
3654    if (width < 1) {
3655        return GLU_INVALID_VALUE;
3656    }
3657
3658    levels = computeLog(width);
3659
3660    levels+= userLevel;
3661    if (!isLegalLevels(userLevel,baseLevel,maxLevel,levels))
3662       return GLU_INVALID_VALUE;
3663
3664    return gluBuild1DMipmapLevelsCore(target, internalFormat,
3665                                      width,
3666                                      width,format, type,
3667                                      userLevel, baseLevel, maxLevel,
3668                                      data);
3669 } /* gluBuild1DMipmapLevels() */
3670
3671 GLint GLAPIENTRY
3672 gluBuild1DMipmaps(GLenum target, GLint internalFormat, GLsizei width,
3673                         GLenum format, GLenum type,
3674                         const void *data)
3675 {
3676    GLint widthPowerOf2;
3677    int levels;
3678    GLint dummy;
3679
3680    int rc= checkMipmapArgs(internalFormat,format,type);
3681    if (rc != 0) return rc;
3682
3683    if (width < 1) {
3684        return GLU_INVALID_VALUE;
3685    }
3686
3687    closestFit(target,width,1,internalFormat,format,type,&widthPowerOf2,&dummy);
3688    levels = computeLog(widthPowerOf2);
3689
3690    return gluBuild1DMipmapLevelsCore(target,internalFormat,
3691                                      width,
3692                                      widthPowerOf2,
3693                                      format,type,0,0,levels,data);
3694 }
3695
3696 static int bitmapBuild2DMipmaps(GLenum target, GLint internalFormat,
3697                      GLint width, GLint height, GLenum format,
3698                      GLenum type, const void *data)
3699 {
3700     GLint newwidth, newheight;
3701     GLint level, levels;
3702     GLushort *newImage;
3703     GLint newImage_width;
3704     GLint newImage_height;
3705     GLushort *otherImage;
3706     GLushort *imageTemp;
3707     GLint memreq;
3708     GLint cmpts;
3709     PixelStorageModes psm;
3710
3711     retrieveStoreModes(&psm);
3712
3713 #if 0
3714     glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxsize);
3715     newwidth = nearestPower(width);
3716     if (newwidth > maxsize) newwidth = maxsize;
3717     newheight = nearestPower(height);
3718     if (newheight > maxsize) newheight = maxsize;
3719 #else
3720     closestFit(target,width,height,internalFormat,format,type,
3721                &newwidth,&newheight);
3722 #endif
3723     levels = computeLog(newwidth);
3724     level = computeLog(newheight);
3725     if (level > levels) levels=level;
3726
3727     otherImage = NULL;
3728     newImage = (GLushort *)
3729         malloc(image_size(width, height, format, GL_UNSIGNED_SHORT));
3730     newImage_width = width;
3731     newImage_height = height;
3732     if (newImage == NULL) {
3733         return GLU_OUT_OF_MEMORY;
3734     }
3735
3736     fill_image(&psm,width, height, format, type, is_index(format),
3737           data, newImage);
3738
3739     cmpts = elements_per_group(format,type);
3740     glPixelStorei(GL_UNPACK_ALIGNMENT, 2);
3741     glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
3742     glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
3743     glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
3744     /*
3745     ** If swap_bytes was set, swapping occurred in fill_image.
3746     */
3747     glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE);
3748
3749     for (level = 0; level <= levels; level++) {
3750         if (newImage_width == newwidth && newImage_height == newheight) {            /* Use newImage for this level */
3751             glTexImage2D(target, level, internalFormat, newImage_width,
3752                     newImage_height, 0, format, GL_UNSIGNED_SHORT,
3753                     (void *) newImage);
3754         } else {
3755             if (otherImage == NULL) {
3756                 memreq =
3757                     image_size(newwidth, newheight, format, GL_UNSIGNED_SHORT);
3758                 otherImage = (GLushort *) malloc(memreq);
3759                 if (otherImage == NULL) {
3760                     glPixelStorei(GL_UNPACK_ALIGNMENT, psm.unpack_alignment);
3761                     glPixelStorei(GL_UNPACK_SKIP_ROWS, psm.unpack_skip_rows);
3762                     glPixelStorei(GL_UNPACK_SKIP_PIXELS,psm.unpack_skip_pixels);
3763                     glPixelStorei(GL_UNPACK_ROW_LENGTH, psm.unpack_row_length);
3764                     glPixelStorei(GL_UNPACK_SWAP_BYTES, psm.unpack_swap_bytes);
3765                     free(newImage);
3766                     return GLU_OUT_OF_MEMORY;
3767                 }
3768             }
3769             scale_internal(cmpts, newImage_width, newImage_height, newImage,
3770                     newwidth, newheight, otherImage);
3771             /* Swap newImage and otherImage */
3772             imageTemp = otherImage;
3773             otherImage = newImage;
3774             newImage = imageTemp;
3775
3776             newImage_width = newwidth;
3777             newImage_height = newheight;
3778             glTexImage2D(target, level, internalFormat, newImage_width,
3779                     newImage_height, 0, format, GL_UNSIGNED_SHORT,
3780                     (void *) newImage);
3781         }
3782         if (newwidth > 1) newwidth /= 2;
3783         if (newheight > 1) newheight /= 2;
3784     }
3785     glPixelStorei(GL_UNPACK_ALIGNMENT, psm.unpack_alignment);
3786     glPixelStorei(GL_UNPACK_SKIP_ROWS, psm.unpack_skip_rows);
3787     glPixelStorei(GL_UNPACK_SKIP_PIXELS, psm.unpack_skip_pixels);
3788     glPixelStorei(GL_UNPACK_ROW_LENGTH, psm.unpack_row_length);
3789     glPixelStorei(GL_UNPACK_SWAP_BYTES, psm.unpack_swap_bytes);
3790
3791     free((GLbyte *) newImage);
3792     if (otherImage) {
3793         free((GLbyte *) otherImage);
3794     }
3795     return 0;
3796 }
3797
3798 /* To make swapping images less error prone */
3799 #define __GLU_INIT_SWAP_IMAGE void *tmpImage
3800 #define __GLU_SWAP_IMAGE(a,b) tmpImage = a; a = b; b = tmpImage;
3801
3802 static int gluBuild2DMipmapLevelsCore(GLenum target, GLint internalFormat,
3803                                       GLsizei width, GLsizei height,
3804                                       GLsizei widthPowerOf2,
3805                                       GLsizei heightPowerOf2,
3806                                       GLenum format, GLenum type,
3807                                       GLint userLevel,
3808                                       GLint baseLevel,GLint maxLevel,
3809                                       const void *data)
3810 {
3811     GLint newwidth, newheight;
3812     GLint level, levels;
3813     const void *usersImage; /* passed from user. Don't touch! */
3814     void *srcImage, *dstImage; /* scratch area to build mipmapped images */
3815     __GLU_INIT_SWAP_IMAGE;
3816     GLint memreq;
3817     GLint cmpts;
3818
3819     GLint myswap_bytes, groups_per_line, element_size, group_size;
3820     GLint rowsize, padding;
3821     PixelStorageModes psm;
3822
3823     assert(checkMipmapArgs(internalFormat,format,type) == 0);
3824     assert(width >= 1 && height >= 1);
3825
3826     if(type == GL_BITMAP) {
3827         return bitmapBuild2DMipmaps(target, internalFormat, width, height,
3828                 format, type, data);
3829     }
3830
3831     srcImage = dstImage = NULL;
3832
3833     newwidth= widthPowerOf2;
3834     newheight= heightPowerOf2;
3835     levels = computeLog(newwidth);
3836     level = computeLog(newheight);
3837     if (level > levels) levels=level;
3838
3839     levels+= userLevel;
3840
3841     retrieveStoreModes(&psm);
3842     myswap_bytes = psm.unpack_swap_bytes;
3843     cmpts = elements_per_group(format,type);
3844     if (psm.unpack_row_length > 0) {
3845         groups_per_line = psm.unpack_row_length;
3846     } else {
3847         groups_per_line = width;
3848     }
3849
3850     element_size = bytes_per_element(type);
3851     group_size = element_size * cmpts;
3852     if (element_size == 1) myswap_bytes = 0;
3853
3854     rowsize = groups_per_line * group_size;
3855     padding = (rowsize % psm.unpack_alignment);
3856     if (padding) {
3857         rowsize += psm.unpack_alignment - padding;
3858     }
3859     usersImage = (const GLubyte *) data + psm.unpack_skip_rows * rowsize +
3860         psm.unpack_skip_pixels * group_size;
3861
3862     glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
3863     glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
3864     glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
3865
3866     level = userLevel;
3867
3868     /* already power-of-two square */
3869     if (width == newwidth && height == newheight) {
3870         /* Use usersImage for level userLevel */
3871         if (baseLevel <= level && level <= maxLevel) {
3872         glPixelStorei(GL_UNPACK_ROW_LENGTH, psm.unpack_row_length);
3873         glTexImage2D(target, level, internalFormat, width,
3874                 height, 0, format, type,
3875                 usersImage);
3876         }
3877         glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
3878         if(levels == 0) { /* we're done. clean up and return */
3879           glPixelStorei(GL_UNPACK_ALIGNMENT, psm.unpack_alignment);
3880           glPixelStorei(GL_UNPACK_SKIP_ROWS, psm.unpack_skip_rows);
3881           glPixelStorei(GL_UNPACK_SKIP_PIXELS, psm.unpack_skip_pixels);
3882           glPixelStorei(GL_UNPACK_ROW_LENGTH, psm.unpack_row_length);
3883           glPixelStorei(GL_UNPACK_SWAP_BYTES, psm.unpack_swap_bytes);
3884           return 0;
3885         }
3886         {
3887            int nextWidth= newwidth/2;
3888            int nextHeight= newheight/2;
3889
3890            /* clamp to 1 */
3891            if (nextWidth < 1) nextWidth= 1;
3892            if (nextHeight < 1) nextHeight= 1;
3893         memreq = image_size(nextWidth, nextHeight, format, type);
3894         }
3895
3896         switch(type) {
3897         case GL_UNSIGNED_BYTE:
3898           dstImage = (GLubyte *)malloc(memreq);
3899           break;
3900         case GL_BYTE:
3901           dstImage = (GLbyte *)malloc(memreq);
3902           break;
3903         case GL_UNSIGNED_SHORT:
3904           dstImage = (GLushort *)malloc(memreq);
3905           break;
3906         case GL_SHORT:
3907           dstImage = (GLshort *)malloc(memreq);
3908           break;
3909         case GL_UNSIGNED_INT:
3910           dstImage = (GLuint *)malloc(memreq);
3911           break;
3912         case GL_INT:
3913           dstImage = (GLint *)malloc(memreq);
3914           break;
3915         case GL_FLOAT:
3916           dstImage = (GLfloat *)malloc(memreq);
3917           break;
3918         case GL_UNSIGNED_BYTE_3_3_2:
3919         case GL_UNSIGNED_BYTE_2_3_3_REV:
3920           dstImage = (GLubyte *)malloc(memreq);
3921           break;
3922         case GL_UNSIGNED_SHORT_5_6_5:
3923         case GL_UNSIGNED_SHORT_5_6_5_REV:
3924         case GL_UNSIGNED_SHORT_4_4_4_4:
3925         case GL_UNSIGNED_SHORT_4_4_4_4_REV:
3926         case GL_UNSIGNED_SHORT_5_5_5_1:
3927         case GL_UNSIGNED_SHORT_1_5_5_5_REV:
3928           dstImage = (GLushort *)malloc(memreq);
3929           break;
3930         case GL_UNSIGNED_INT_8_8_8_8:
3931         case GL_UNSIGNED_INT_8_8_8_8_REV:
3932         case GL_UNSIGNED_INT_10_10_10_2:
3933         case GL_UNSIGNED_INT_2_10_10_10_REV:
3934           dstImage = (GLuint *)malloc(memreq);  
3935           break;
3936         default:
3937           return GLU_INVALID_ENUM;
3938         }
3939         if (dstImage == NULL) {
3940           glPixelStorei(GL_UNPACK_ALIGNMENT, psm.unpack_alignment);
3941           glPixelStorei(GL_UNPACK_SKIP_ROWS, psm.unpack_skip_rows);
3942           glPixelStorei(GL_UNPACK_SKIP_PIXELS, psm.unpack_skip_pixels);
3943           glPixelStorei(GL_UNPACK_ROW_LENGTH, psm.unpack_row_length);
3944           glPixelStorei(GL_UNPACK_SWAP_BYTES, psm.unpack_swap_bytes);
3945           return GLU_OUT_OF_MEMORY;
3946         }
3947         else
3948           switch(type) {
3949           case GL_UNSIGNED_BYTE:
3950             halveImage_ubyte(cmpts, width, height,
3951                              (const GLubyte *)usersImage, (GLubyte *)dstImage,
3952                              element_size, rowsize, group_size);
3953             break;
3954           case GL_BYTE:
3955             halveImage_byte(cmpts, width, height,
3956                             (const GLbyte *)usersImage, (GLbyte *)dstImage,
3957                             element_size, rowsize, group_size);
3958             break;
3959           case GL_UNSIGNED_SHORT:
3960             halveImage_ushort(cmpts, width, height,
3961                               (const GLushort *)usersImage, (GLushort *)dstImage,
3962                               element_size, rowsize, group_size, myswap_bytes);
3963             break;
3964           case GL_SHORT:
3965             halveImage_short(cmpts, width, height,
3966                              (const GLshort *)usersImage, (GLshort *)dstImage,
3967                              element_size, rowsize, group_size, myswap_bytes);
3968             break;
3969           case GL_UNSIGNED_INT:
3970             halveImage_uint(cmpts, width, height,
3971                             (const GLuint *)usersImage, (GLuint *)dstImage,
3972                             element_size, rowsize, group_size, myswap_bytes);
3973             break;
3974           case GL_INT:
3975             halveImage_int(cmpts, width, height,
3976                            (const GLint *)usersImage, (GLint *)dstImage,
3977                            element_size, rowsize, group_size, myswap_bytes);
3978             break;
3979           case GL_FLOAT:
3980             halveImage_float(cmpts, width, height,
3981                              (const GLfloat *)usersImage, (GLfloat *)dstImage,
3982                              element_size, rowsize, group_size, myswap_bytes);
3983             break;
3984           case GL_UNSIGNED_BYTE_3_3_2:
3985             assert(format == GL_RGB);
3986             halveImagePackedPixel(3,extract332,shove332,
3987                                   width,height,usersImage,dstImage,
3988                                   element_size,rowsize,myswap_bytes);
3989             break;
3990           case GL_UNSIGNED_BYTE_2_3_3_REV:
3991             assert(format == GL_RGB);
3992             halveImagePackedPixel(3,extract233rev,shove233rev,
3993                                   width,height,usersImage,dstImage,
3994                                   element_size,rowsize,myswap_bytes);
3995             break;
3996           case GL_UNSIGNED_SHORT_5_6_5:
3997             halveImagePackedPixel(3,extract565,shove565,
3998                                   width,height,usersImage,dstImage,
3999                                   element_size,rowsize,myswap_bytes);
4000             break;
4001           case GL_UNSIGNED_SHORT_5_6_5_REV:
4002             halveImagePackedPixel(3,extract565rev,shove565rev,
4003                                   width,height,usersImage,dstImage,
4004                                   element_size,rowsize,myswap_bytes);
4005             break;
4006           case GL_UNSIGNED_SHORT_4_4_4_4:
4007             halveImagePackedPixel(4,extract4444,shove4444,
4008                                   width,height,usersImage,dstImage,
4009                                   element_size,rowsize,myswap_bytes);
4010             break;
4011           case GL_UNSIGNED_SHORT_4_4_4_4_REV:
4012             halveImagePackedPixel(4,extract4444rev,shove4444rev,
4013                                   width,height,usersImage,dstImage,
4014                                   element_size,rowsize,myswap_bytes);
4015             break;
4016           case GL_UNSIGNED_SHORT_5_5_5_1:
4017             halveImagePackedPixel(4,extract5551,shove5551,
4018                                   width,height,usersImage,dstImage,
4019                                   element_size,rowsize,myswap_bytes);
4020             break;
4021           case GL_UNSIGNED_SHORT_1_5_5_5_REV:
4022             halveImagePackedPixel(4,extract1555rev,shove1555rev,
4023                                   width,height,usersImage,dstImage,
4024                                   element_size,rowsize,myswap_bytes);
4025             break;
4026           case GL_UNSIGNED_INT_8_8_8_8:
4027             halveImagePackedPixel(4,extract8888,shove8888,
4028                                   width,height,usersImage,dstImage,
4029                                   element_size,rowsize,myswap_bytes);
4030             break;
4031           case GL_UNSIGNED_INT_8_8_8_8_REV:
4032             halveImagePackedPixel(4,extract8888rev,shove8888rev,
4033                                   width,height,usersImage,dstImage,
4034                                   element_size,rowsize,myswap_bytes);
4035             break;
4036           case GL_UNSIGNED_INT_10_10_10_2:
4037             halveImagePackedPixel(4,extract1010102,shove1010102,
4038                                   width,height,usersImage,dstImage,
4039                                   element_size,rowsize,myswap_bytes);
4040             break;
4041           case GL_UNSIGNED_INT_2_10_10_10_REV:
4042             halveImagePackedPixel(4,extract2101010rev,shove2101010rev,
4043                                   width,height,usersImage,dstImage,
4044                                   element_size,rowsize,myswap_bytes);
4045             break;
4046           default:
4047             assert(0);
4048             break;
4049           }
4050         newwidth = width/2;
4051         newheight = height/2;
4052         /* clamp to 1 */
4053         if (newwidth < 1) newwidth= 1;
4054         if (newheight < 1) newheight= 1;
4055
4056         myswap_bytes = 0;
4057         rowsize = newwidth * group_size;
4058         memreq = image_size(newwidth, newheight, format, type);
4059         /* Swap srcImage and dstImage */
4060         __GLU_SWAP_IMAGE(srcImage,dstImage);
4061         switch(type) {
4062         case GL_UNSIGNED_BYTE:
4063           dstImage = (GLubyte *)malloc(memreq);
4064           break;
4065         case GL_BYTE:
4066           dstImage = (GLbyte *)malloc(memreq);
4067           break;
4068         case GL_UNSIGNED_SHORT:
4069           dstImage = (GLushort *)malloc(memreq);
4070           break;
4071         case GL_SHORT:
4072           dstImage = (GLshort *)malloc(memreq);
4073           break;
4074         case GL_UNSIGNED_INT:
4075           dstImage = (GLuint *)malloc(memreq);
4076           break;
4077         case GL_INT:
4078           dstImage = (GLint *)malloc(memreq);
4079           break;
4080         case GL_FLOAT:
4081           dstImage = (GLfloat *)malloc(memreq);
4082           break;
4083         case GL_UNSIGNED_BYTE_3_3_2:
4084         case GL_UNSIGNED_BYTE_2_3_3_REV:
4085           dstImage = (GLubyte *)malloc(memreq);
4086           break;
4087         case GL_UNSIGNED_SHORT_5_6_5:
4088         case GL_UNSIGNED_SHORT_5_6_5_REV:
4089         case GL_UNSIGNED_SHORT_4_4_4_4:
4090         case GL_UNSIGNED_SHORT_4_4_4_4_REV:
4091         case GL_UNSIGNED_SHORT_5_5_5_1:
4092         case GL_UNSIGNED_SHORT_1_5_5_5_REV:
4093           dstImage = (GLushort *)malloc(memreq);
4094           break;
4095         case GL_UNSIGNED_INT_8_8_8_8:
4096         case GL_UNSIGNED_INT_8_8_8_8_REV:
4097         case GL_UNSIGNED_INT_10_10_10_2:
4098         case GL_UNSIGNED_INT_2_10_10_10_REV:
4099           dstImage = (GLuint *)malloc(memreq);
4100           break;
4101         default:
4102           return GLU_INVALID_ENUM;
4103         }
4104         if (dstImage == NULL) {
4105           glPixelStorei(GL_UNPACK_ALIGNMENT, psm.unpack_alignment);
4106           glPixelStorei(GL_UNPACK_SKIP_ROWS, psm.unpack_skip_rows);
4107           glPixelStorei(GL_UNPACK_SKIP_PIXELS, psm.unpack_skip_pixels);
4108           glPixelStorei(GL_UNPACK_ROW_LENGTH, psm.unpack_row_length);
4109           glPixelStorei(GL_UNPACK_SWAP_BYTES, psm.unpack_swap_bytes);
4110           free(srcImage);
4111           return GLU_OUT_OF_MEMORY;
4112         }
4113         /* level userLevel+1 is in srcImage; level userLevel already saved */
4114         level = userLevel+1;
4115     } else { /* user's image is *not* nice power-of-2 sized square */
4116         memreq = image_size(newwidth, newheight, format, type);
4117         switch(type) {
4118             case GL_UNSIGNED_BYTE:
4119                 dstImage = (GLubyte *)malloc(memreq);
4120                 break;
4121             case GL_BYTE:
4122                 dstImage = (GLbyte *)malloc(memreq);
4123                 break;
4124             case GL_UNSIGNED_SHORT:
4125                 dstImage = (GLushort *)malloc(memreq);
4126                 break;
4127             case GL_SHORT:
4128                 dstImage = (GLshort *)malloc(memreq);
4129                 break;
4130             case GL_UNSIGNED_INT:
4131                 dstImage = (GLuint *)malloc(memreq);
4132                 break;
4133             case GL_INT:
4134                 dstImage = (GLint *)malloc(memreq);
4135                 break;
4136             case GL_FLOAT:
4137                 dstImage = (GLfloat *)malloc(memreq);
4138                 break;
4139             case GL_UNSIGNED_BYTE_3_3_2:
4140             case GL_UNSIGNED_BYTE_2_3_3_REV:
4141                 dstImage = (GLubyte *)malloc(memreq);
4142                 break;
4143             case GL_UNSIGNED_SHORT_5_6_5:
4144             case GL_UNSIGNED_SHORT_5_6_5_REV:
4145             case GL_UNSIGNED_SHORT_4_4_4_4:
4146             case GL_UNSIGNED_SHORT_4_4_4_4_REV:
4147             case GL_UNSIGNED_SHORT_5_5_5_1:
4148             case GL_UNSIGNED_SHORT_1_5_5_5_REV:
4149                 dstImage = (GLushort *)malloc(memreq);
4150                 break;
4151             case GL_UNSIGNED_INT_8_8_8_8:
4152             case GL_UNSIGNED_INT_8_8_8_8_REV:
4153             case GL_UNSIGNED_INT_10_10_10_2:
4154             case GL_UNSIGNED_INT_2_10_10_10_REV:
4155                 dstImage = (GLuint *)malloc(memreq);
4156                 break;
4157             default:
4158                 return GLU_INVALID_ENUM;
4159         }
4160
4161         if (dstImage == NULL) {
4162             glPixelStorei(GL_UNPACK_ALIGNMENT, psm.unpack_alignment);
4163             glPixelStorei(GL_UNPACK_SKIP_ROWS, psm.unpack_skip_rows);
4164             glPixelStorei(GL_UNPACK_SKIP_PIXELS, psm.unpack_skip_pixels);
4165             glPixelStorei(GL_UNPACK_ROW_LENGTH, psm.unpack_row_length);
4166             glPixelStorei(GL_UNPACK_SWAP_BYTES, psm.unpack_swap_bytes);
4167             return GLU_OUT_OF_MEMORY;
4168         }
4169
4170         switch(type) {
4171         case GL_UNSIGNED_BYTE:
4172             scale_internal_ubyte(cmpts, width, height,
4173                                  (const GLubyte *)usersImage, newwidth, newheight,
4174                                  (GLubyte *)dstImage, element_size,
4175                                  rowsize, group_size);
4176             break;
4177         case GL_BYTE:
4178             scale_internal_byte(cmpts, width, height,
4179                                 (const GLbyte *)usersImage, newwidth, newheight,
4180                                 (GLbyte *)dstImage, element_size,
4181                                 rowsize, group_size);
4182             break;
4183         case GL_UNSIGNED_SHORT:
4184             scale_internal_ushort(cmpts, width, height,
4185                                   (const GLushort *)usersImage, newwidth, newheight,
4186                                   (GLushort *)dstImage, element_size,
4187                                   rowsize, group_size, myswap_bytes);
4188             break;
4189         case GL_SHORT:
4190             scale_internal_short(cmpts, width, height,
4191                                  (const GLshort *)usersImage, newwidth, newheight,
4192                                  (GLshort *)dstImage, element_size,
4193                                  rowsize, group_size, myswap_bytes);
4194             break;
4195         case GL_UNSIGNED_INT:
4196             scale_internal_uint(cmpts, width, height,
4197                                 (const GLuint *)usersImage, newwidth, newheight,
4198                                 (GLuint *)dstImage, element_size,
4199                                 rowsize, group_size, myswap_bytes);
4200             break;
4201         case GL_INT:
4202             scale_internal_int(cmpts, width, height,
4203                                (const GLint *)usersImage, newwidth, newheight,
4204                                (GLint *)dstImage, element_size,
4205                                rowsize, group_size, myswap_bytes);
4206             break;
4207         case GL_FLOAT:
4208             scale_internal_float(cmpts, width, height,
4209                                  (const GLfloat *)usersImage, newwidth, newheight,
4210                                  (GLfloat *)dstImage, element_size,
4211                                  rowsize, group_size, myswap_bytes);
4212             break;
4213         case GL_UNSIGNED_BYTE_3_3_2:
4214             scaleInternalPackedPixel(3,extract332,shove332,
4215                                      width, height,usersImage,
4216                                      newwidth,newheight,(void *)dstImage,
4217                                      element_size,rowsize,myswap_bytes);
4218             break;
4219         case GL_UNSIGNED_BYTE_2_3_3_REV:
4220             scaleInternalPackedPixel(3,extract233rev,shove233rev,
4221                                      width, height,usersImage,
4222                                      newwidth,newheight,(void *)dstImage,
4223                                      element_size,rowsize,myswap_bytes);
4224             break;
4225         case GL_UNSIGNED_SHORT_5_6_5:
4226             scaleInternalPackedPixel(3,extract565,shove565,
4227                                      width, height,usersImage,
4228                                      newwidth,newheight,(void *)dstImage,
4229                                      element_size,rowsize,myswap_bytes);
4230             break;
4231         case GL_UNSIGNED_SHORT_5_6_5_REV:
4232             scaleInternalPackedPixel(3,extract565rev,shove565rev,
4233                                      width, height,usersImage,
4234                                      newwidth,newheight,(void *)dstImage,
4235                                      element_size,rowsize,myswap_bytes);
4236             break;
4237         case GL_UNSIGNED_SHORT_4_4_4_4:
4238             scaleInternalPackedPixel(4,extract4444,shove4444,
4239                                      width, height,usersImage,
4240                                      newwidth,newheight,(void *)dstImage,
4241                                      element_size,rowsize,myswap_bytes);
4242             break;
4243         case GL_UNSIGNED_SHORT_4_4_4_4_REV:
4244             scaleInternalPackedPixel(4,extract4444rev,shove4444rev,
4245                                      width, height,usersImage,
4246                                      newwidth,newheight,(void *)dstImage,
4247                                      element_size,rowsize,myswap_bytes);
4248             break;
4249         case GL_UNSIGNED_SHORT_5_5_5_1:
4250             scaleInternalPackedPixel(4,extract5551,shove5551,
4251                                      width, height,usersImage,
4252                                      newwidth,newheight,(void *)dstImage,
4253                                      element_size,rowsize,myswap_bytes);
4254             break;
4255         case GL_UNSIGNED_SHORT_1_5_5_5_REV:
4256             scaleInternalPackedPixel(4,extract1555rev,shove1555rev,
4257                                      width, height,usersImage,
4258                                      newwidth,newheight,(void *)dstImage,
4259                                      element_size,rowsize,myswap_bytes);
4260             break;
4261         case GL_UNSIGNED_INT_8_8_8_8:
4262             scaleInternalPackedPixel(4,extract8888,shove8888,
4263                                      width, height,usersImage,
4264                                      newwidth,newheight,(void *)dstImage,
4265                                      element_size,rowsize,myswap_bytes);
4266             break;
4267         case GL_UNSIGNED_INT_8_8_8_8_REV:
4268             scaleInternalPackedPixel(4,extract8888rev,shove8888rev,
4269                                      width, height,usersImage,
4270                                      newwidth,newheight,(void *)dstImage,
4271                                      element_size,rowsize,myswap_bytes);
4272             break;
4273         case GL_UNSIGNED_INT_10_10_10_2:
4274             scaleInternalPackedPixel(4,extract1010102,shove1010102,
4275                                      width, height,usersImage,
4276                                      newwidth,newheight,(void *)dstImage,
4277                                      element_size,rowsize,myswap_bytes);
4278             break;
4279         case GL_UNSIGNED_INT_2_10_10_10_REV:
4280             scaleInternalPackedPixel(4,extract2101010rev,shove2101010rev,
4281                                      width, height,usersImage,
4282                                      newwidth,newheight,(void *)dstImage,
4283                                      element_size,rowsize,myswap_bytes);
4284             break;
4285         default:
4286             assert(0);
4287             break;
4288         }
4289         myswap_bytes = 0;
4290         rowsize = newwidth * group_size;
4291         /* Swap dstImage and srcImage */
4292         __GLU_SWAP_IMAGE(srcImage,dstImage);
4293
4294         if(levels != 0) { /* use as little memory as possible */
4295           {
4296              int nextWidth= newwidth/2;
4297              int nextHeight= newheight/2;
4298              if (nextWidth < 1) nextWidth= 1;
4299              if (nextHeight < 1) nextHeight= 1; 
4300
4301           memreq = image_size(nextWidth, nextHeight, format, type);
4302           }
4303
4304           switch(type) {
4305           case GL_UNSIGNED_BYTE:
4306             dstImage = (GLubyte *)malloc(memreq);
4307             break;
4308           case GL_BYTE:
4309             dstImage = (GLbyte *)malloc(memreq);
4310             break;
4311           case GL_UNSIGNED_SHORT:
4312             dstImage = (GLushort *)malloc(memreq);
4313             break;
4314           case GL_SHORT:
4315             dstImage = (GLshort *)malloc(memreq);
4316             break;
4317           case GL_UNSIGNED_INT:
4318             dstImage = (GLuint *)malloc(memreq);
4319             break;
4320           case GL_INT:
4321             dstImage = (GLint *)malloc(memreq);
4322             break;
4323           case GL_FLOAT:
4324             dstImage = (GLfloat *)malloc(memreq);
4325             break;
4326           case GL_UNSIGNED_BYTE_3_3_2:
4327           case GL_UNSIGNED_BYTE_2_3_3_REV:
4328             dstImage = (GLubyte *)malloc(memreq);
4329             break;
4330           case GL_UNSIGNED_SHORT_5_6_5:
4331           case GL_UNSIGNED_SHORT_5_6_5_REV:
4332           case GL_UNSIGNED_SHORT_4_4_4_4:
4333           case GL_UNSIGNED_SHORT_4_4_4_4_REV:
4334           case GL_UNSIGNED_SHORT_5_5_5_1:
4335           case GL_UNSIGNED_SHORT_1_5_5_5_REV:
4336             dstImage = (GLushort *)malloc(memreq);
4337             break;
4338           case GL_UNSIGNED_INT_8_8_8_8:
4339           case GL_UNSIGNED_INT_8_8_8_8_REV:
4340           case GL_UNSIGNED_INT_10_10_10_2:
4341           case GL_UNSIGNED_INT_2_10_10_10_REV:
4342             dstImage = (GLuint *)malloc(memreq);
4343             break;
4344           default:
4345             return GLU_INVALID_ENUM;
4346           }
4347           if (dstImage == NULL) {
4348             glPixelStorei(GL_UNPACK_ALIGNMENT, psm.unpack_alignment);
4349             glPixelStorei(GL_UNPACK_SKIP_ROWS, psm.unpack_skip_rows);
4350             glPixelStorei(GL_UNPACK_SKIP_PIXELS, psm.unpack_skip_pixels);
4351             glPixelStorei(GL_UNPACK_ROW_LENGTH, psm.unpack_row_length);
4352             glPixelStorei(GL_UNPACK_SWAP_BYTES, psm.unpack_swap_bytes);
4353             free(srcImage);
4354             return GLU_OUT_OF_MEMORY;
4355           }
4356         }
4357         /* level userLevel is in srcImage; nothing saved yet */
4358         level = userLevel;
4359     }
4360
4361     glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE);
4362     if (baseLevel <= level && level <= maxLevel) {
4363     glTexImage2D(target, level, internalFormat, newwidth, newheight, 0,
4364                  format, type, (void *)srcImage);
4365     }
4366
4367     level++; /* update current level for the loop */
4368     for (; level <= levels; level++) {
4369         switch(type) {
4370             case GL_UNSIGNED_BYTE:
4371                 halveImage_ubyte(cmpts, newwidth, newheight,
4372                 (GLubyte *)srcImage, (GLubyte *)dstImage, element_size,
4373                 rowsize, group_size);
4374                 break;
4375             case GL_BYTE:
4376                 halveImage_byte(cmpts, newwidth, newheight,
4377                 (GLbyte *)srcImage, (GLbyte *)dstImage, element_size,
4378                 rowsize, group_size);
4379                 break;
4380             case GL_UNSIGNED_SHORT:
4381                 halveImage_ushort(cmpts, newwidth, newheight,
4382                 (GLushort *)srcImage, (GLushort *)dstImage, element_size,
4383                 rowsize, group_size, myswap_bytes);
4384                 break;
4385             case GL_SHORT:
4386                 halveImage_short(cmpts, newwidth, newheight,
4387                 (GLshort *)srcImage, (GLshort *)dstImage, element_size,
4388                 rowsize, group_size, myswap_bytes);
4389                 break;
4390             case GL_UNSIGNED_INT:
4391                 halveImage_uint(cmpts, newwidth, newheight,
4392                 (GLuint *)srcImage, (GLuint *)dstImage, element_size,
4393                 rowsize, group_size, myswap_bytes);
4394                 break;
4395             case GL_INT:
4396                 halveImage_int(cmpts, newwidth, newheight,
4397                 (GLint *)srcImage, (GLint *)dstImage, element_size,
4398                 rowsize, group_size, myswap_bytes);
4399                 break;
4400             case GL_FLOAT:
4401                 halveImage_float(cmpts, newwidth, newheight,
4402                 (GLfloat *)srcImage, (GLfloat *)dstImage, element_size,
4403                 rowsize, group_size, myswap_bytes);
4404                 break;
4405             case GL_UNSIGNED_BYTE_3_3_2:
4406                 halveImagePackedPixel(3,extract332,shove332,
4407                                       newwidth,newheight,
4408                                       srcImage,dstImage,element_size,rowsize,
4409                                       myswap_bytes);
4410                 break;
4411             case GL_UNSIGNED_BYTE_2_3_3_REV:
4412                 halveImagePackedPixel(3,extract233rev,shove233rev,
4413                                       newwidth,newheight,
4414                                       srcImage,dstImage,element_size,rowsize,
4415                                       myswap_bytes);
4416                 break;
4417             case GL_UNSIGNED_SHORT_5_6_5:
4418                 halveImagePackedPixel(3,extract565,shove565,
4419                                       newwidth,newheight,
4420                                       srcImage,dstImage,element_size,rowsize,
4421                                       myswap_bytes);
4422                 break;
4423             case GL_UNSIGNED_SHORT_5_6_5_REV:
4424                 halveImagePackedPixel(3,extract565rev,shove565rev,
4425                                       newwidth,newheight,
4426                                       srcImage,dstImage,element_size,rowsize,
4427                                       myswap_bytes);
4428                 break;
4429             case GL_UNSIGNED_SHORT_4_4_4_4:
4430                 halveImagePackedPixel(4,extract4444,shove4444,
4431                                       newwidth,newheight,
4432                                       srcImage,dstImage,element_size,rowsize,
4433                                       myswap_bytes);
4434                 break;
4435             case GL_UNSIGNED_SHORT_4_4_4_4_REV:
4436                 halveImagePackedPixel(4,extract4444rev,shove4444rev,
4437                                       newwidth,newheight,
4438                                       srcImage,dstImage,element_size,rowsize,
4439                                       myswap_bytes);
4440                 break;
4441             case GL_UNSIGNED_SHORT_5_5_5_1:             
4442                 halveImagePackedPixel(4,extract5551,shove5551,
4443                                       newwidth,newheight,
4444                                       srcImage,dstImage,element_size,rowsize,
4445                                       myswap_bytes);
4446                 break;
4447             case GL_UNSIGNED_SHORT_1_5_5_5_REV:                 
4448                 halveImagePackedPixel(4,extract1555rev,shove1555rev,
4449                                       newwidth,newheight,
4450                                       srcImage,dstImage,element_size,rowsize,
4451                                       myswap_bytes);
4452                 break;
4453             case GL_UNSIGNED_INT_8_8_8_8:
4454                 halveImagePackedPixel(4,extract8888,shove8888,
4455                                       newwidth,newheight,
4456                                       srcImage,dstImage,element_size,rowsize,
4457                                       myswap_bytes);
4458                 break;
4459             case GL_UNSIGNED_INT_8_8_8_8_REV:
4460                 halveImagePackedPixel(4,extract8888rev,shove8888rev,
4461                                       newwidth,newheight,
4462                                       srcImage,dstImage,element_size,rowsize,
4463                                       myswap_bytes);
4464                 break;
4465             case GL_UNSIGNED_INT_10_10_10_2:
4466                 halveImagePackedPixel(4,extract1010102,shove1010102,
4467                                       newwidth,newheight,
4468                                       srcImage,dstImage,element_size,rowsize,
4469                                       myswap_bytes);
4470                 break;
4471             case GL_UNSIGNED_INT_2_10_10_10_REV:
4472                 halveImagePackedPixel(4,extract2101010rev,shove2101010rev,
4473                                       newwidth,newheight,
4474                                       srcImage,dstImage,element_size,rowsize,
4475                                       myswap_bytes);
4476                 break;
4477             default:
4478                 assert(0);
4479                 break;
4480         }
4481
4482         __GLU_SWAP_IMAGE(srcImage,dstImage);
4483
4484         if (newwidth > 1) { newwidth /= 2; rowsize /= 2;}
4485         if (newheight > 1) newheight /= 2;
4486       {
4487        /* compute amount to pad per row, if any */
4488        int rowPad= rowsize % psm.unpack_alignment;
4489
4490        /* should row be padded? */
4491        if (rowPad == 0) {       /* nope, row should not be padded */
4492            /* call tex image with srcImage untouched since it's not padded */
4493            if (baseLevel <= level && level <= maxLevel) {
4494            glTexImage2D(target, level, internalFormat, newwidth, newheight, 0,
4495            format, type, (void *) srcImage);
4496            }
4497        }
4498        else {                   /* yes, row should be padded */
4499           /* compute length of new row in bytes, including padding */
4500           int newRowLength= rowsize + psm.unpack_alignment - rowPad;
4501           int ii; unsigned char *dstTrav, *srcTrav; /* indices for copying */
4502
4503           /* allocate new image for mipmap of size newRowLength x newheight */
4504           void *newMipmapImage= malloc((size_t) (newRowLength*newheight));
4505           if (newMipmapImage == NULL) {
4506              /* out of memory so return */
4507              glPixelStorei(GL_UNPACK_ALIGNMENT, psm.unpack_alignment);
4508              glPixelStorei(GL_UNPACK_SKIP_ROWS, psm.unpack_skip_rows);
4509              glPixelStorei(GL_UNPACK_SKIP_PIXELS, psm.unpack_skip_pixels);
4510              glPixelStorei(GL_UNPACK_ROW_LENGTH, psm.unpack_row_length);
4511              glPixelStorei(GL_UNPACK_SWAP_BYTES, psm.unpack_swap_bytes);
4512              return GLU_OUT_OF_MEMORY;
4513           }
4514
4515           /* copy image from srcImage into newMipmapImage by rows */
4516           for (ii= 0,
4517                dstTrav= (unsigned char *) newMipmapImage,
4518                srcTrav= (unsigned char *) srcImage;
4519                ii< newheight;
4520                ii++,
4521                dstTrav+= newRowLength, /* make sure the correct distance... */
4522                srcTrav+= rowsize) {    /* ...is skipped */
4523              memcpy(dstTrav,srcTrav,rowsize);
4524              /* note that the pad bytes are not visited and will contain
4525               * garbage, which is ok.
4526               */
4527           }
4528
4529           /* ...and use this new image for mipmapping instead */
4530           if (baseLevel <= level && level <= maxLevel) {
4531           glTexImage2D(target, level, internalFormat, newwidth, newheight, 0,
4532                        format, type, newMipmapImage);
4533           }
4534           free(newMipmapImage); /* don't forget to free it! */
4535        } /* else */
4536       }
4537     } /* for level */
4538     glPixelStorei(GL_UNPACK_ALIGNMENT, psm.unpack_alignment);
4539     glPixelStorei(GL_UNPACK_SKIP_ROWS, psm.unpack_skip_rows);
4540     glPixelStorei(GL_UNPACK_SKIP_PIXELS, psm.unpack_skip_pixels);
4541     glPixelStorei(GL_UNPACK_ROW_LENGTH, psm.unpack_row_length);
4542     glPixelStorei(GL_UNPACK_SWAP_BYTES, psm.unpack_swap_bytes);
4543
4544     free(srcImage); /*if you get to here, a srcImage has always been malloc'ed*/
4545     if (dstImage) { /* if it's non-rectangular and only 1 level */
4546       free(dstImage);
4547     }
4548     return 0;
4549 } /* gluBuild2DMipmapLevelsCore() */
4550
4551 GLint GLAPIENTRY
4552 gluBuild2DMipmapLevels(GLenum target, GLint internalFormat,
4553                              GLsizei width, GLsizei height,
4554                              GLenum format, GLenum type,
4555                              GLint userLevel, GLint baseLevel, GLint maxLevel,
4556                              const void *data)
4557 {
4558    int level, levels;
4559
4560    int rc= checkMipmapArgs(internalFormat,format,type);
4561    if (rc != 0) return rc;
4562
4563    if (width < 1 || height < 1) {
4564        return GLU_INVALID_VALUE;
4565    }
4566
4567    levels = computeLog(width);
4568    level = computeLog(height);
4569    if (level > levels) levels=level;
4570
4571    levels+= userLevel;
4572    if (!isLegalLevels(userLevel,baseLevel,maxLevel,levels))
4573       return GLU_INVALID_VALUE;
4574
4575    return gluBuild2DMipmapLevelsCore(target, internalFormat,
4576                                      width, height,
4577                                      width, height,
4578                                      format, type,
4579                                      userLevel, baseLevel, maxLevel,
4580                                      data);
4581 } /* gluBuild2DMipmapLevels() */
4582
4583 GLint GLAPIENTRY
4584 gluBuild2DMipmaps(GLenum target, GLint internalFormat,
4585                         GLsizei width, GLsizei height,
4586                         GLenum format, GLenum type,
4587                         const void *data)
4588 {
4589    GLint widthPowerOf2, heightPowerOf2;
4590    int level, levels;
4591
4592    int rc= checkMipmapArgs(internalFormat,format,type);
4593    if (rc != 0) return rc;
4594
4595    if (width < 1 || height < 1) {
4596        return GLU_INVALID_VALUE;
4597    }
4598
4599    closestFit(target,width,height,internalFormat,format,type,
4600               &widthPowerOf2,&heightPowerOf2);
4601
4602    levels = computeLog(widthPowerOf2);
4603    level = computeLog(heightPowerOf2);
4604    if (level > levels) levels=level;
4605
4606    return gluBuild2DMipmapLevelsCore(target,internalFormat,
4607                                      width, height,
4608                                      widthPowerOf2,heightPowerOf2,
4609                                      format,type,
4610                                      0,0,levels,data);
4611 }  /* gluBuild2DMipmaps() */
4612
4613 #if 0
4614 /*
4615 ** This routine is for the limited case in which
4616 **      type == GL_UNSIGNED_BYTE && format != index  &&
4617 **      unpack_alignment = 1 && unpack_swap_bytes == false
4618 **
4619 ** so all of the work data can be kept as ubytes instead of shorts.
4620 */
4621 static int fastBuild2DMipmaps(const PixelStorageModes *psm,
4622                        GLenum target, GLint components, GLint width,
4623                      GLint height, GLenum format,
4624                      GLenum type, void *data)
4625 {
4626     GLint newwidth, newheight;
4627     GLint level, levels;
4628     GLubyte *newImage;
4629     GLint newImage_width;
4630     GLint newImage_height;
4631     GLubyte *otherImage;
4632     GLubyte *imageTemp;
4633     GLint memreq;
4634     GLint cmpts;
4635
4636
4637 #if 0
4638     glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxsize);
4639     newwidth = nearestPower(width);
4640     if (newwidth > maxsize) newwidth = maxsize;
4641     newheight = nearestPower(height);
4642     if (newheight > maxsize) newheight = maxsize;
4643 #else
4644     closestFit(target,width,height,components,format,type,
4645                &newwidth,&newheight);
4646 #endif
4647     levels = computeLog(newwidth);
4648     level = computeLog(newheight);
4649     if (level > levels) levels=level;
4650
4651     cmpts = elements_per_group(format,type);
4652
4653     otherImage = NULL;
4654     /**
4655     ** No need to copy the user data if its in the packed correctly.
4656     ** Make sure that later routines don't change that data.
4657     */
4658     if (psm->unpack_skip_rows == 0 && psm->unpack_skip_pixels == 0) {
4659         newImage = (GLubyte *)data;
4660         newImage_width = width;
4661         newImage_height = height;
4662     } else {
4663         GLint rowsize;
4664         GLint groups_per_line;
4665         GLint elements_per_line;
4666         const GLubyte *start;
4667         const GLubyte *iter;
4668         GLubyte *iter2;
4669         GLint i, j;
4670
4671         newImage = (GLubyte *)
4672             malloc(image_size(width, height, format, GL_UNSIGNED_BYTE));
4673         newImage_width = width;
4674         newImage_height = height;
4675         if (newImage == NULL) {
4676             return GLU_OUT_OF_MEMORY;
4677         }
4678
4679         /*
4680         ** Abbreviated version of fill_image for this restricted case.
4681         */
4682         if (psm->unpack_row_length > 0) {
4683             groups_per_line = psm->unpack_row_length;
4684         } else {
4685             groups_per_line = width;
4686         }
4687         rowsize = groups_per_line * cmpts;
4688         elements_per_line = width * cmpts;
4689         start = (const GLubyte *) data + psm->unpack_skip_rows * rowsize +
4690                 psm->unpack_skip_pixels * cmpts;
4691         iter2 = newImage;
4692
4693         for (i = 0; i < height; i++) {
4694             iter = start;
4695             for (j = 0; j < elements_per_line; j++) {
4696                 *iter2 = *iter;
4697                 iter++;
4698                 iter2++;
4699             }
4700             start += rowsize;
4701         }
4702     }
4703
4704
4705     glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
4706     glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
4707     glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
4708     glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
4709     glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE);
4710
4711     for (level = 0; level <= levels; level++) {
4712         if (newImage_width == newwidth && newImage_height == newheight) {
4713             /* Use newImage for this level */
4714             glTexImage2D(target, level, components, newImage_width,
4715                     newImage_height, 0, format, GL_UNSIGNED_BYTE,
4716                     (void *) newImage);
4717         } else {
4718             if (otherImage == NULL) {
4719                 memreq =
4720                     image_size(newwidth, newheight, format, GL_UNSIGNED_BYTE);
4721                 otherImage = (GLubyte *) malloc(memreq);
4722                 if (otherImage == NULL) {
4723                     glPixelStorei(GL_UNPACK_ALIGNMENT, psm->unpack_alignment);
4724                     glPixelStorei(GL_UNPACK_SKIP_ROWS, psm->unpack_skip_rows);
4725                     glPixelStorei(GL_UNPACK_SKIP_PIXELS, psm->unpack_skip_pixels);
4726                     glPixelStorei(GL_UNPACK_ROW_LENGTH,psm->unpack_row_length);
4727                     glPixelStorei(GL_UNPACK_SWAP_BYTES,psm->unpack_swap_bytes);
4728                     return GLU_OUT_OF_MEMORY;
4729                 }
4730             }
4731 /*
4732             scale_internal_ubyte(cmpts, newImage_width, newImage_height,
4733                     newImage, newwidth, newheight, otherImage);
4734 */
4735             /* Swap newImage and otherImage */
4736             imageTemp = otherImage;
4737             otherImage = newImage;
4738             newImage = imageTemp;
4739
4740             newImage_width = newwidth;
4741             newImage_height = newheight;
4742             glTexImage2D(target, level, components, newImage_width,
4743                     newImage_height, 0, format, GL_UNSIGNED_BYTE,
4744                     (void *) newImage);
4745         }
4746         if (newwidth > 1) newwidth /= 2;
4747         if (newheight > 1) newheight /= 2;
4748     }
4749     glPixelStorei(GL_UNPACK_ALIGNMENT, psm->unpack_alignment);
4750     glPixelStorei(GL_UNPACK_SKIP_ROWS, psm->unpack_skip_rows);
4751     glPixelStorei(GL_UNPACK_SKIP_PIXELS, psm->unpack_skip_pixels);
4752     glPixelStorei(GL_UNPACK_ROW_LENGTH, psm->unpack_row_length);
4753     glPixelStorei(GL_UNPACK_SWAP_BYTES, psm->unpack_swap_bytes);
4754
4755     if (newImage != (const GLubyte *)data) {
4756         free((GLbyte *) newImage);
4757     }
4758     if (otherImage && otherImage != (const GLubyte *)data) {
4759         free((GLbyte *) otherImage);
4760     }
4761     return 0;
4762 }
4763 #endif
4764
4765 /*
4766  * Utility Routines
4767  */
4768 static GLint elements_per_group(GLenum format, GLenum type)
4769 {
4770     /*
4771      * Return the number of elements per group of a specified format
4772      */
4773
4774     /* If the type is packedpixels then answer is 1 (ignore format) */
4775     if (type == GL_UNSIGNED_BYTE_3_3_2 ||
4776         type == GL_UNSIGNED_BYTE_2_3_3_REV ||
4777         type == GL_UNSIGNED_SHORT_5_6_5 ||
4778         type == GL_UNSIGNED_SHORT_5_6_5_REV ||
4779         type == GL_UNSIGNED_SHORT_4_4_4_4 ||
4780         type == GL_UNSIGNED_SHORT_4_4_4_4_REV ||
4781         type == GL_UNSIGNED_SHORT_5_5_5_1  ||
4782         type == GL_UNSIGNED_SHORT_1_5_5_5_REV  ||
4783         type == GL_UNSIGNED_INT_8_8_8_8 ||
4784         type == GL_UNSIGNED_INT_8_8_8_8_REV ||
4785         type == GL_UNSIGNED_INT_10_10_10_2 ||
4786         type == GL_UNSIGNED_INT_2_10_10_10_REV) {
4787         return 1;
4788     }
4789
4790     /* Types are not packed pixels, so get elements per group */
4791     switch(format) {
4792       case GL_RGB:
4793       case GL_BGR:
4794         return 3;
4795       case GL_LUMINANCE_ALPHA:
4796         return 2;
4797       case GL_RGBA:
4798       case GL_BGRA:
4799         return 4;
4800       default:
4801         return 1;
4802     }
4803 }
4804
4805 static GLfloat bytes_per_element(GLenum type)
4806 {
4807     /*
4808      * Return the number of bytes per element, based on the element type
4809      */
4810     switch(type) {
4811       case GL_BITMAP:
4812         return 1.0 / 8.0;
4813       case GL_UNSIGNED_SHORT:
4814         return(sizeof(GLushort));
4815       case GL_SHORT:
4816         return(sizeof(GLshort));
4817       case GL_UNSIGNED_BYTE:
4818         return(sizeof(GLubyte));
4819       case GL_BYTE:
4820         return(sizeof(GLbyte));
4821       case GL_INT:
4822         return(sizeof(GLint));
4823       case GL_UNSIGNED_INT:
4824         return(sizeof(GLuint));
4825       case GL_FLOAT:
4826         return(sizeof(GLfloat));
4827       case GL_UNSIGNED_BYTE_3_3_2:
4828       case GL_UNSIGNED_BYTE_2_3_3_REV:  
4829         return(sizeof(GLubyte));
4830       case GL_UNSIGNED_SHORT_5_6_5:
4831       case GL_UNSIGNED_SHORT_5_6_5_REV:
4832       case GL_UNSIGNED_SHORT_4_4_4_4:
4833       case GL_UNSIGNED_SHORT_4_4_4_4_REV:
4834       case GL_UNSIGNED_SHORT_5_5_5_1:
4835       case GL_UNSIGNED_SHORT_1_5_5_5_REV:
4836         return(sizeof(GLushort));
4837       case GL_UNSIGNED_INT_8_8_8_8:
4838       case GL_UNSIGNED_INT_8_8_8_8_REV:
4839       case GL_UNSIGNED_INT_10_10_10_2:
4840       case GL_UNSIGNED_INT_2_10_10_10_REV:
4841         return(sizeof(GLuint));
4842       default:
4843         return 4;
4844     }
4845 }
4846
4847 static GLint is_index(GLenum format)
4848 {
4849     return format == GL_COLOR_INDEX || format == GL_STENCIL_INDEX;
4850 }
4851
4852 /*
4853 ** Compute memory required for internal packed array of data of given type
4854 ** and format.
4855 */
4856 static GLint image_size(GLint width, GLint height, GLenum format, GLenum type)
4857 {
4858     int bytes_per_row;
4859     int components;
4860
4861 assert(width > 0);
4862 assert(height > 0);
4863     components = elements_per_group(format,type);
4864     if (type == GL_BITMAP) {
4865         bytes_per_row = (width + 7) / 8;
4866     } else {
4867         bytes_per_row = bytes_per_element(type) * width;
4868     }
4869     return bytes_per_row * height * components;
4870 }
4871
4872 /*
4873 ** Extract array from user's data applying all pixel store modes.
4874 ** The internal format used is an array of unsigned shorts.
4875 */
4876 static void fill_image(const PixelStorageModes *psm,
4877                        GLint width, GLint height, GLenum format,
4878                        GLenum type, GLboolean index_format,
4879                        const void *userdata, GLushort *newimage)
4880 {
4881     GLint components;
4882     GLint element_size;
4883     GLint rowsize;
4884     GLint padding;
4885     GLint groups_per_line;
4886     GLint group_size;
4887     GLint elements_per_line;
4888     const GLubyte *start;
4889     const GLubyte *iter;
4890     GLushort *iter2;
4891     GLint i, j, k;
4892     GLint myswap_bytes;
4893
4894     myswap_bytes = psm->unpack_swap_bytes;
4895     components = elements_per_group(format,type);
4896     if (psm->unpack_row_length > 0) {
4897         groups_per_line = psm->unpack_row_length;
4898     } else {
4899         groups_per_line = width;
4900     }
4901
4902     /* All formats except GL_BITMAP fall out trivially */
4903     if (type == GL_BITMAP) {
4904         GLint bit_offset;
4905         GLint current_bit;
4906
4907         rowsize = (groups_per_line * components + 7) / 8;
4908         padding = (rowsize % psm->unpack_alignment);
4909         if (padding) {
4910             rowsize += psm->unpack_alignment - padding;
4911         }
4912         start = (const GLubyte *) userdata + psm->unpack_skip_rows * rowsize +
4913                 (psm->unpack_skip_pixels * components / 8);
4914         elements_per_line = width * components;
4915         iter2 = newimage;
4916         for (i = 0; i < height; i++) {
4917             iter = start;
4918             bit_offset = (psm->unpack_skip_pixels * components) % 8;
4919             for (j = 0; j < elements_per_line; j++) {
4920                 /* Retrieve bit */
4921                 if (psm->unpack_lsb_first) {
4922                     current_bit = iter[0] & (1 << bit_offset);
4923                 } else {
4924                     current_bit = iter[0] & (1 << (7 - bit_offset));
4925                 }
4926                 if (current_bit) {
4927                     if (index_format) {
4928                         *iter2 = 1;
4929                     } else {
4930                         *iter2 = 65535;
4931                     }
4932                 } else {
4933                     *iter2 = 0;
4934                 }
4935                 bit_offset++;
4936                 if (bit_offset == 8) {
4937                     bit_offset = 0;
4938                     iter++;
4939                 }
4940                 iter2++;
4941             }
4942             start += rowsize;
4943         }
4944     } else {
4945         element_size = bytes_per_element(type);
4946         group_size = element_size * components;
4947         if (element_size == 1) myswap_bytes = 0;
4948
4949         rowsize = groups_per_line * group_size;
4950         padding = (rowsize % psm->unpack_alignment);
4951         if (padding) {
4952             rowsize += psm->unpack_alignment - padding;
4953         }
4954         start = (const GLubyte *) userdata + psm->unpack_skip_rows * rowsize +
4955                 psm->unpack_skip_pixels * group_size;
4956         elements_per_line = width * components;
4957
4958         iter2 = newimage;
4959         for (i = 0; i < height; i++) {
4960             iter = start;
4961             for (j = 0; j < elements_per_line; j++) {
4962                 Type_Widget widget;
4963                 float extractComponents[4];
4964
4965                 switch(type) {
4966                   case GL_UNSIGNED_BYTE_3_3_2:
4967                     extract332(0,iter,extractComponents);
4968                     for (k = 0; k < 3; k++) {
4969                       *iter2++ = (GLushort)(extractComponents[k]*65535);
4970                     }
4971                     break;
4972                   case GL_UNSIGNED_BYTE_2_3_3_REV:
4973                     extract233rev(0,iter,extractComponents);
4974                     for (k = 0; k < 3; k++) {
4975                       *iter2++ = (GLushort)(extractComponents[k]*65535);
4976                     }
4977                     break;
4978                   case GL_UNSIGNED_BYTE:
4979                     if (index_format) {
4980                         *iter2++ = *iter;
4981                     } else {
4982                         *iter2++ = (*iter) * 257;
4983                     }
4984                     break;
4985                   case GL_BYTE:
4986                     if (index_format) {
4987                         *iter2++ = *((const GLbyte *) iter);
4988                     } else {
4989                         /* rough approx */
4990                         *iter2++ = (*((const GLbyte *) iter)) * 516;
4991                     }
4992                     break;
4993                   case GL_UNSIGNED_SHORT_5_6_5:                         
4994                     extract565(myswap_bytes,iter,extractComponents);
4995                     for (k = 0; k < 3; k++) {
4996                       *iter2++ = (GLushort)(extractComponents[k]*65535);
4997                     }
4998                     break;
4999                   case GL_UNSIGNED_SHORT_5_6_5_REV:                     
5000                     extract565rev(myswap_bytes,iter,extractComponents);
5001                     for (k = 0; k < 3; k++) {
5002                       *iter2++ = (GLushort)(extractComponents[k]*65535);
5003                     }
5004                     break;
5005                   case GL_UNSIGNED_SHORT_4_4_4_4:               
5006                     extract4444(myswap_bytes,iter,extractComponents);
5007                     for (k = 0; k < 4; k++) {
5008                       *iter2++ = (GLushort)(extractComponents[k]*65535);
5009                     }
5010                     break;
5011                   case GL_UNSIGNED_SHORT_4_4_4_4_REV:           
5012                     extract4444rev(myswap_bytes,iter,extractComponents);
5013                     for (k = 0; k < 4; k++) {
5014                       *iter2++ = (GLushort)(extractComponents[k]*65535);
5015                     }
5016                     break;
5017                   case GL_UNSIGNED_SHORT_5_5_5_1:               
5018                     extract5551(myswap_bytes,iter,extractComponents);
5019                     for (k = 0; k < 4; k++) {
5020                       *iter2++ = (GLushort)(extractComponents[k]*65535);
5021                     }
5022                     break;
5023                   case GL_UNSIGNED_SHORT_1_5_5_5_REV:
5024                     extract1555rev(myswap_bytes,iter,extractComponents);
5025                     for (k = 0; k < 4; k++) {
5026                       *iter2++ = (GLushort)(extractComponents[k]*65535);
5027                     }
5028                     break;
5029                   case GL_UNSIGNED_SHORT:
5030                   case GL_SHORT:
5031                     if (myswap_bytes) {
5032                         widget.ub[0] = iter[1];
5033                         widget.ub[1] = iter[0];
5034                     } else {
5035                         widget.ub[0] = iter[0];
5036                         widget.ub[1] = iter[1];
5037                     }
5038                     if (type == GL_SHORT) {
5039                         if (index_format) {
5040                             *iter2++ = widget.s[0];
5041                         } else {
5042                             /* rough approx */
5043                             *iter2++ = widget.s[0]*2;
5044                         }
5045                     } else {
5046                         *iter2++ = widget.us[0];
5047                     }
5048                     break;
5049                   case GL_UNSIGNED_INT_8_8_8_8:         
5050                     extract8888(myswap_bytes,iter,extractComponents);
5051                     for (k = 0; k < 4; k++) {
5052                       *iter2++ = (GLushort)(extractComponents[k]*65535);
5053                     }
5054                     break;
5055                   case GL_UNSIGNED_INT_8_8_8_8_REV:             
5056                     extract8888rev(myswap_bytes,iter,extractComponents);
5057                     for (k = 0; k < 4; k++) {
5058                       *iter2++ = (GLushort)(extractComponents[k]*65535);
5059                     }
5060                     break;
5061                   case GL_UNSIGNED_INT_10_10_10_2:              
5062                     extract1010102(myswap_bytes,iter,extractComponents);
5063                     for (k = 0; k < 4; k++) {
5064                       *iter2++ = (GLushort)(extractComponents[k]*65535);
5065                     }
5066                     break;
5067                   case GL_UNSIGNED_INT_2_10_10_10_REV:
5068                     extract2101010rev(myswap_bytes,iter,extractComponents);
5069                     for (k = 0; k < 4; k++) {
5070                       *iter2++ = (GLushort)(extractComponents[k]*65535);
5071                     }
5072                     break;
5073                   case GL_INT:
5074                   case GL_UNSIGNED_INT:
5075                   case GL_FLOAT:
5076                     if (myswap_bytes) {
5077                         widget.ub[0] = iter[3];
5078                         widget.ub[1] = iter[2];
5079                         widget.ub[2] = iter[1];
5080                         widget.ub[3] = iter[0];
5081                     } else {
5082                         widget.ub[0] = iter[0];
5083                         widget.ub[1] = iter[1];
5084                         widget.ub[2] = iter[2];
5085                         widget.ub[3] = iter[3];
5086                     }
5087                     if (type == GL_FLOAT) {
5088                         if (index_format) {
5089                             *iter2++ = widget.f;
5090                         } else {
5091                             *iter2++ = 65535 * widget.f;
5092                         }
5093                     } else if (type == GL_UNSIGNED_INT) {
5094                         if (index_format) {
5095                             *iter2++ = widget.ui;
5096                         } else {
5097                             *iter2++ = widget.ui >> 16;
5098                         }
5099                     } else {
5100                         if (index_format) {
5101                             *iter2++ = widget.i;
5102                         } else {
5103                             *iter2++ = widget.i >> 15;
5104                         }
5105                     }
5106                     break;
5107                 }
5108                 iter += element_size;
5109             } /* for j */
5110             start += rowsize;
5111 #if 1
5112             /* want 'iter' pointing at start, not within, row for assertion
5113              * purposes
5114              */
5115             iter= start;        
5116 #endif
5117         } /* for i */
5118
5119        /* iterators should be one byte past end */
5120        if (!isTypePackedPixel(type)) {
5121           assert(iter2 == &newimage[width*height*components]);
5122        }
5123        else {
5124           assert(iter2 == &newimage[width*height*
5125                                     elements_per_group(format,0)]);
5126        }
5127        assert( iter == &((const GLubyte *)userdata)[rowsize*height +
5128                                         psm->unpack_skip_rows * rowsize +
5129                                         psm->unpack_skip_pixels * group_size] );
5130
5131     } /* else */
5132 } /* fill_image() */
5133
5134 /*
5135 ** Insert array into user's data applying all pixel store modes.
5136 ** The internal format is an array of unsigned shorts.
5137 ** empty_image() because it is the opposite of fill_image().
5138 */
5139 static void empty_image(const PixelStorageModes *psm,
5140                         GLint width, GLint height, GLenum format,
5141                         GLenum type, GLboolean index_format,
5142                         const GLushort *oldimage, void *userdata)
5143 {
5144     GLint components;
5145     GLint element_size;
5146     GLint rowsize;
5147     GLint padding;
5148     GLint groups_per_line;
5149     GLint group_size;
5150     GLint elements_per_line;
5151     GLubyte *start;
5152     GLubyte *iter;
5153     const GLushort *iter2;
5154     GLint i, j, k;
5155     GLint myswap_bytes;
5156
5157     myswap_bytes = psm->pack_swap_bytes;
5158     components = elements_per_group(format,type);
5159     if (psm->pack_row_length > 0) {
5160         groups_per_line = psm->pack_row_length;
5161     } else {
5162         groups_per_line = width;
5163     }
5164
5165     /* All formats except GL_BITMAP fall out trivially */
5166     if (type == GL_BITMAP) {
5167         GLint bit_offset;
5168         GLint current_bit;
5169
5170         rowsize = (groups_per_line * components + 7) / 8;
5171         padding = (rowsize % psm->pack_alignment);
5172         if (padding) {
5173             rowsize += psm->pack_alignment - padding;
5174         }
5175         start = (GLubyte *) userdata + psm->pack_skip_rows * rowsize +
5176                 (psm->pack_skip_pixels * components / 8);
5177         elements_per_line = width * components;
5178         iter2 = oldimage;
5179         for (i = 0; i < height; i++) {
5180             iter = start;
5181             bit_offset = (psm->pack_skip_pixels * components) % 8;
5182             for (j = 0; j < elements_per_line; j++) {
5183                 if (index_format) {
5184                     current_bit = iter2[0] & 1;
5185                 } else {
5186                     if (iter2[0] > 32767) {
5187                         current_bit = 1;
5188                     } else {
5189                         current_bit = 0;
5190                     }
5191                 }
5192
5193                 if (current_bit) {
5194                     if (psm->pack_lsb_first) {
5195                         *iter |= (1 << bit_offset);
5196                     } else {
5197                         *iter |= (1 << (7 - bit_offset));
5198                     }
5199                 } else {
5200                     if (psm->pack_lsb_first) {
5201                         *iter &= ~(1 << bit_offset);
5202                     } else {
5203                         *iter &= ~(1 << (7 - bit_offset));
5204                     }
5205                 }
5206
5207                 bit_offset++;
5208                 if (bit_offset == 8) {
5209                     bit_offset = 0;
5210                     iter++;
5211                 }
5212                 iter2++;
5213             }
5214             start += rowsize;
5215         }
5216     } else {
5217         float shoveComponents[4];
5218
5219         element_size = bytes_per_element(type);
5220         group_size = element_size * components;
5221         if (element_size == 1) myswap_bytes = 0;
5222
5223         rowsize = groups_per_line * group_size;
5224         padding = (rowsize % psm->pack_alignment);
5225         if (padding) {
5226             rowsize += psm->pack_alignment - padding;
5227         }
5228         start = (GLubyte *) userdata + psm->pack_skip_rows * rowsize +
5229                 psm->pack_skip_pixels * group_size;
5230         elements_per_line = width * components;
5231
5232         iter2 = oldimage;
5233         for (i = 0; i < height; i++) {
5234             iter = start;
5235             for (j = 0; j < elements_per_line; j++) {
5236                 Type_Widget widget;
5237
5238                 switch(type) {
5239                   case GL_UNSIGNED_BYTE_3_3_2:
5240                     for (k = 0; k < 3; k++) {
5241                        shoveComponents[k]= *iter2++ / 65535.0;
5242                     }
5243                     shove332(shoveComponents,0,(void *)iter);
5244                     break;
5245                   case GL_UNSIGNED_BYTE_2_3_3_REV:
5246                     for (k = 0; k < 3; k++) {
5247                        shoveComponents[k]= *iter2++ / 65535.0;
5248                     }
5249                     shove233rev(shoveComponents,0,(void *)iter);
5250                     break;
5251                   case GL_UNSIGNED_BYTE:
5252                     if (index_format) {
5253                         *iter = *iter2++;
5254                     } else {
5255                         *iter = *iter2++ >> 8;
5256                     }
5257                     break;
5258                   case GL_BYTE:
5259                     if (index_format) {
5260                         *((GLbyte *) iter) = *iter2++;
5261                     } else {
5262                         *((GLbyte *) iter) = *iter2++ >> 9;
5263                     }
5264                     break;
5265                   case GL_UNSIGNED_SHORT_5_6_5:         
5266                     for (k = 0; k < 3; k++) {
5267                        shoveComponents[k]= *iter2++ / 65535.0;
5268                     }
5269                     shove565(shoveComponents,0,(void *)&widget.us[0]);
5270                     if (myswap_bytes) {
5271                        iter[0] = widget.ub[1];
5272                        iter[1] = widget.ub[0];
5273                     }
5274                     else {
5275                        *(GLushort *)iter = widget.us[0];
5276                     }
5277                     break;
5278                   case GL_UNSIGNED_SHORT_5_6_5_REV:             
5279                     for (k = 0; k < 3; k++) {
5280                        shoveComponents[k]= *iter2++ / 65535.0;
5281                     }
5282                     shove565rev(shoveComponents,0,(void *)&widget.us[0]);
5283                     if (myswap_bytes) {
5284                        iter[0] = widget.ub[1];
5285                        iter[1] = widget.ub[0];
5286                     }
5287                     else {
5288                        *(GLushort *)iter = widget.us[0];
5289                     }
5290                     break;
5291                   case GL_UNSIGNED_SHORT_4_4_4_4:
5292                     for (k = 0; k < 4; k++) {
5293                        shoveComponents[k]= *iter2++ / 65535.0;
5294                     }
5295                     shove4444(shoveComponents,0,(void *)&widget.us[0]);
5296                     if (myswap_bytes) {
5297                        iter[0] = widget.ub[1];
5298                        iter[1] = widget.ub[0];
5299                     } else {
5300                        *(GLushort *)iter = widget.us[0];
5301                     }
5302                     break;
5303                   case GL_UNSIGNED_SHORT_4_4_4_4_REV:
5304                     for (k = 0; k < 4; k++) {
5305                        shoveComponents[k]= *iter2++ / 65535.0;
5306                     }
5307                     shove4444rev(shoveComponents,0,(void *)&widget.us[0]);
5308                     if (myswap_bytes) {
5309                        iter[0] = widget.ub[1];
5310                        iter[1] = widget.ub[0];
5311                     } else {
5312                        *(GLushort *)iter = widget.us[0];
5313                     }
5314                     break;
5315                   case GL_UNSIGNED_SHORT_5_5_5_1:
5316                     for (k = 0; k < 4; k++) {
5317                        shoveComponents[k]= *iter2++ / 65535.0;
5318                     }
5319                     shove5551(shoveComponents,0,(void *)&widget.us[0]);
5320                     if (myswap_bytes) {
5321                        iter[0] = widget.ub[1];
5322                        iter[1] = widget.ub[0];
5323                     } else {
5324                        *(GLushort *)iter = widget.us[0];
5325                     }
5326                     break;
5327                   case GL_UNSIGNED_SHORT_1_5_5_5_REV:
5328                     for (k = 0; k < 4; k++) {
5329                        shoveComponents[k]= *iter2++ / 65535.0;
5330                     }
5331                     shove1555rev(shoveComponents,0,(void *)&widget.us[0]);
5332                     if (myswap_bytes) {
5333                        iter[0] = widget.ub[1];
5334                        iter[1] = widget.ub[0];
5335                     } else {
5336                        *(GLushort *)iter = widget.us[0];
5337                     }
5338                     break;
5339                   case GL_UNSIGNED_SHORT:
5340                   case GL_SHORT:
5341                     if (type == GL_SHORT) {
5342                         if (index_format) {
5343                             widget.s[0] = *iter2++;
5344                         } else {
5345                             widget.s[0] = *iter2++ >> 1;
5346                         }
5347                     } else {
5348                         widget.us[0] = *iter2++;
5349                     }
5350                     if (myswap_bytes) {
5351                         iter[0] = widget.ub[1];
5352                         iter[1] = widget.ub[0];
5353                     } else {
5354                         iter[0] = widget.ub[0];
5355                         iter[1] = widget.ub[1];
5356                     }
5357                     break;
5358                   case GL_UNSIGNED_INT_8_8_8_8:
5359                     for (k = 0; k < 4; k++) {
5360                        shoveComponents[k]= *iter2++ / 65535.0;
5361                     }
5362                     shove8888(shoveComponents,0,(void *)&widget.ui);
5363                     if (myswap_bytes) {
5364                         iter[3] = widget.ub[0];
5365                         iter[2] = widget.ub[1];
5366                         iter[1] = widget.ub[2];
5367                         iter[0] = widget.ub[3];
5368                     } else {
5369                         *(GLuint *)iter= widget.ui;
5370                     }
5371
5372                     break;
5373                   case GL_UNSIGNED_INT_8_8_8_8_REV:
5374                     for (k = 0; k < 4; k++) {
5375                        shoveComponents[k]= *iter2++ / 65535.0;
5376                     }
5377                     shove8888rev(shoveComponents,0,(void *)&widget.ui);
5378                     if (myswap_bytes) {
5379                         iter[3] = widget.ub[0];
5380                         iter[2] = widget.ub[1];
5381                         iter[1] = widget.ub[2];
5382                         iter[0] = widget.ub[3];
5383                     } else {
5384                         *(GLuint *)iter= widget.ui;
5385                     }
5386                     break;
5387                   case GL_UNSIGNED_INT_10_10_10_2:
5388                     for (k = 0; k < 4; k++) {
5389                        shoveComponents[k]= *iter2++ / 65535.0;
5390                     }
5391                     shove1010102(shoveComponents,0,(void *)&widget.ui);
5392                     if (myswap_bytes) {
5393                         iter[3] = widget.ub[0];
5394                         iter[2] = widget.ub[1];
5395                         iter[1] = widget.ub[2];
5396                         iter[0] = widget.ub[3];
5397                     } else {
5398                         *(GLuint *)iter= widget.ui;
5399                     }
5400                     break;
5401                   case GL_UNSIGNED_INT_2_10_10_10_REV:
5402                     for (k = 0; k < 4; k++) {
5403                        shoveComponents[k]= *iter2++ / 65535.0;
5404                     }
5405                     shove2101010rev(shoveComponents,0,(void *)&widget.ui);
5406                     if (myswap_bytes) {
5407                         iter[3] = widget.ub[0];
5408                         iter[2] = widget.ub[1];
5409                         iter[1] = widget.ub[2];
5410                         iter[0] = widget.ub[3];
5411                     } else {
5412                         *(GLuint *)iter= widget.ui;
5413                     }
5414                     break;
5415                   case GL_INT:
5416                   case GL_UNSIGNED_INT:
5417                   case GL_FLOAT:
5418                     if (type == GL_FLOAT) {
5419                         if (index_format) {
5420                             widget.f = *iter2++;
5421                         } else {
5422                             widget.f = *iter2++ / (float) 65535.0;
5423                         }
5424                     } else if (type == GL_UNSIGNED_INT) {
5425                         if (index_format) {
5426                             widget.ui = *iter2++;
5427                         } else {
5428                             widget.ui = (unsigned int) *iter2++ * 65537;
5429                         }
5430                     } else {
5431                         if (index_format) {
5432                             widget.i = *iter2++;
5433                         } else {
5434                             widget.i = ((unsigned int) *iter2++ * 65537)/2;
5435                         }
5436                     }
5437                     if (myswap_bytes) {
5438                         iter[3] = widget.ub[0];
5439                         iter[2] = widget.ub[1];
5440                         iter[1] = widget.ub[2];
5441                         iter[0] = widget.ub[3];
5442                     } else {
5443                         iter[0] = widget.ub[0];
5444                         iter[1] = widget.ub[1];
5445                         iter[2] = widget.ub[2];
5446                         iter[3] = widget.ub[3];
5447                     }
5448                     break;
5449                 }
5450                 iter += element_size;
5451             } /* for j */
5452             start += rowsize;
5453 #if 1
5454             /* want 'iter' pointing at start, not within, row for assertion
5455              * purposes
5456              */
5457             iter= start;        
5458 #endif
5459         } /* for i */
5460
5461         /* iterators should be one byte past end */
5462         if (!isTypePackedPixel(type)) {
5463            assert(iter2 == &oldimage[width*height*components]);
5464         }
5465         else {
5466            assert(iter2 == &oldimage[width*height*
5467                                      elements_per_group(format,0)]);
5468         }
5469         assert( iter == &((GLubyte *)userdata)[rowsize*height +
5470                                         psm->pack_skip_rows * rowsize +
5471                                         psm->pack_skip_pixels * group_size] );
5472
5473     } /* else */
5474 } /* empty_image() */
5475
5476 /*--------------------------------------------------------------------------
5477  * Decimation of packed pixel types
5478  *--------------------------------------------------------------------------
5479  */
5480 static void extract332(int isSwap,
5481                        const void *packedPixel, GLfloat extractComponents[])
5482 {
5483    GLubyte ubyte= *(const GLubyte *)packedPixel;
5484
5485    isSwap= isSwap;              /* turn off warnings */
5486
5487    /* 11100000 == 0xe0 */
5488    /* 00011100 == 0x1c */
5489    /* 00000011 == 0x03 */
5490
5491    extractComponents[0]=   (float)((ubyte & 0xe0)  >> 5) / 7.0;
5492    extractComponents[1]=   (float)((ubyte & 0x1c)  >> 2) / 7.0; /* 7 = 2^3-1 */
5493    extractComponents[2]=   (float)((ubyte & 0x03)      ) / 3.0; /* 3 = 2^2-1 */
5494 } /* extract332() */
5495
5496 static void shove332(const GLfloat shoveComponents[],
5497                      int index, void *packedPixel)      
5498 {
5499    /* 11100000 == 0xe0 */
5500    /* 00011100 == 0x1c */
5501    /* 00000011 == 0x03 */
5502
5503    assert(0.0 <= shoveComponents[0] && shoveComponents[0] <= 1.0);
5504    assert(0.0 <= shoveComponents[1] && shoveComponents[1] <= 1.0);
5505    assert(0.0 <= shoveComponents[2] && shoveComponents[2] <= 1.0);
5506
5507    /* due to limited precision, need to round before shoving */
5508    ((GLubyte *)packedPixel)[index]  =
5509      ((GLubyte)((shoveComponents[0] * 7)+0.5)  << 5) & 0xe0;
5510    ((GLubyte *)packedPixel)[index] |=
5511      ((GLubyte)((shoveComponents[1] * 7)+0.5)  << 2) & 0x1c;
5512    ((GLubyte *)packedPixel)[index]  |=
5513      ((GLubyte)((shoveComponents[2] * 3)+0.5)      ) & 0x03;
5514 } /* shove332() */
5515
5516 static void extract233rev(int isSwap,
5517                           const void *packedPixel, GLfloat extractComponents[])
5518 {
5519    GLubyte ubyte= *(const GLubyte *)packedPixel;
5520
5521    isSwap= isSwap;              /* turn off warnings */
5522
5523    /* 0000,0111 == 0x07 */
5524    /* 0011,1000 == 0x38 */
5525    /* 1100,0000 == 0xC0 */
5526
5527    extractComponents[0]= (float)((ubyte & 0x07)     ) / 7.0;
5528    extractComponents[1]= (float)((ubyte & 0x38) >> 3) / 7.0;
5529    extractComponents[2]= (float)((ubyte & 0xC0) >> 6) / 3.0;
5530 } /* extract233rev() */
5531
5532 static void shove233rev(const GLfloat shoveComponents[],
5533                         int index, void *packedPixel)   
5534 {
5535    /* 0000,0111 == 0x07 */
5536    /* 0011,1000 == 0x38 */
5537    /* 1100,0000 == 0xC0 */
5538
5539    assert(0.0 <= shoveComponents[0] && shoveComponents[0] <= 1.0);
5540    assert(0.0 <= shoveComponents[1] && shoveComponents[1] <= 1.0);
5541    assert(0.0 <= shoveComponents[2] && shoveComponents[2] <= 1.0);
5542
5543    /* due to limited precision, need to round before shoving */
5544    ((GLubyte *)packedPixel)[index] =
5545      ((GLubyte)((shoveComponents[0] * 7.0)+0.5)     ) & 0x07;
5546    ((GLubyte *)packedPixel)[index]|=
5547      ((GLubyte)((shoveComponents[1] * 7.0)+0.5) << 3) & 0x38;
5548    ((GLubyte *)packedPixel)[index]|=
5549      ((GLubyte)((shoveComponents[2] * 3.0)+0.5) << 6) & 0xC0;
5550 } /* shove233rev() */
5551
5552 static void extract565(int isSwap,
5553                        const void *packedPixel, GLfloat extractComponents[])
5554 {
5555    GLushort ushort;
5556
5557    if (isSwap) {
5558      ushort= __GLU_SWAP_2_BYTES(packedPixel);
5559    }
5560    else {
5561      ushort= *(const GLushort *)packedPixel;
5562    }
5563
5564    /* 11111000,00000000 == 0xf800 */
5565    /* 00000111,11100000 == 0x07e0 */
5566    /* 00000000,00011111 == 0x001f */
5567
5568    extractComponents[0]=(float)((ushort & 0xf800) >> 11) / 31.0;/* 31 = 2^5-1*/
5569    extractComponents[1]=(float)((ushort & 0x07e0) >>  5) / 63.0;/* 63 = 2^6-1*/
5570    extractComponents[2]=(float)((ushort & 0x001f)      ) / 31.0;
5571 } /* extract565() */
5572
5573 static void shove565(const GLfloat shoveComponents[],
5574                      int index,void *packedPixel)
5575 {
5576    /* 11111000,00000000 == 0xf800 */
5577    /* 00000111,11100000 == 0x07e0 */
5578    /* 00000000,00011111 == 0x001f */
5579
5580    assert(0.0 <= shoveComponents[0] && shoveComponents[0] <= 1.0);
5581    assert(0.0 <= shoveComponents[1] && shoveComponents[1] <= 1.0);
5582    assert(0.0 <= shoveComponents[2] && shoveComponents[2] <= 1.0);
5583
5584    /* due to limited precision, need to round before shoving */
5585    ((GLushort *)packedPixel)[index] =
5586      ((GLushort)((shoveComponents[0] * 31)+0.5) << 11) & 0xf800;
5587    ((GLushort *)packedPixel)[index]|=
5588      ((GLushort)((shoveComponents[1] * 63)+0.5) <<  5) & 0x07e0;
5589    ((GLushort *)packedPixel)[index]|=
5590      ((GLushort)((shoveComponents[2] * 31)+0.5)      ) & 0x001f;
5591 } /* shove565() */
5592
5593 static void extract565rev(int isSwap,
5594                           const void *packedPixel, GLfloat extractComponents[])
5595 {
5596    GLushort ushort;
5597
5598    if (isSwap) {
5599      ushort= __GLU_SWAP_2_BYTES(packedPixel);
5600    }
5601    else {
5602      ushort= *(const GLushort *)packedPixel;
5603    }
5604
5605    /* 00000000,00011111 == 0x001f */
5606    /* 00000111,11100000 == 0x07e0 */
5607    /* 11111000,00000000 == 0xf800 */
5608
5609    extractComponents[0]= (float)((ushort & 0x001F)      ) / 31.0;
5610    extractComponents[1]= (float)((ushort & 0x07E0) >>  5) / 63.0;
5611    extractComponents[2]= (float)((ushort & 0xF800) >> 11) / 31.0;
5612 } /* extract565rev() */
5613
5614 static void shove565rev(const GLfloat shoveComponents[],
5615                         int index,void *packedPixel)
5616 {
5617    /* 00000000,00011111 == 0x001f */
5618    /* 00000111,11100000 == 0x07e0 */
5619    /* 11111000,00000000 == 0xf800 */
5620
5621    assert(0.0 <= shoveComponents[0] && shoveComponents[0] <= 1.0);
5622    assert(0.0 <= shoveComponents[1] && shoveComponents[1] <= 1.0);
5623    assert(0.0 <= shoveComponents[2] && shoveComponents[2] <= 1.0);
5624
5625    /* due to limited precision, need to round before shoving */
5626    ((GLushort *)packedPixel)[index] =
5627      ((GLushort)((shoveComponents[0] * 31.0)+0.5)      ) & 0x001F;
5628    ((GLushort *)packedPixel)[index]|=
5629      ((GLushort)((shoveComponents[1] * 63.0)+0.5) <<  5) & 0x07E0;
5630    ((GLushort *)packedPixel)[index]|=
5631      ((GLushort)((shoveComponents[2] * 31.0)+0.5) << 11) & 0xF800;
5632 } /* shove565rev() */
5633
5634 static void extract4444(int isSwap,const void *packedPixel,
5635                         GLfloat extractComponents[])
5636 {
5637    GLushort ushort;
5638
5639    if (isSwap) {
5640      ushort= __GLU_SWAP_2_BYTES(packedPixel);
5641    }
5642    else {
5643      ushort= *(const GLushort *)packedPixel;
5644    }
5645
5646    /* 11110000,00000000 == 0xf000 */
5647    /* 00001111,00000000 == 0x0f00 */
5648    /* 00000000,11110000 == 0x00f0 */
5649    /* 00000000,00001111 == 0x000f */
5650
5651    extractComponents[0]= (float)((ushort & 0xf000) >> 12) / 15.0;/* 15=2^4-1 */
5652    extractComponents[1]= (float)((ushort & 0x0f00) >>  8) / 15.0;
5653    extractComponents[2]= (float)((ushort & 0x00f0) >>  4) / 15.0;
5654    extractComponents[3]= (float)((ushort & 0x000f)      ) / 15.0;
5655 } /* extract4444() */
5656
5657 static void shove4444(const GLfloat shoveComponents[],
5658                       int index,void *packedPixel)
5659 {
5660    assert(0.0 <= shoveComponents[0] && shoveComponents[0] <= 1.0);
5661    assert(0.0 <= shoveComponents[1] && shoveComponents[1] <= 1.0);
5662    assert(0.0 <= shoveComponents[2] && shoveComponents[2] <= 1.0);
5663    assert(0.0 <= shoveComponents[3] && shoveComponents[3] <= 1.0);
5664
5665    /* due to limited precision, need to round before shoving */
5666    ((GLushort *)packedPixel)[index] =
5667      ((GLushort)((shoveComponents[0] * 15)+0.5) << 12) & 0xf000;
5668    ((GLushort *)packedPixel)[index]|=
5669      ((GLushort)((shoveComponents[1] * 15)+0.5) <<  8) & 0x0f00;
5670    ((GLushort *)packedPixel)[index]|=
5671      ((GLushort)((shoveComponents[2] * 15)+0.5) <<  4) & 0x00f0;
5672    ((GLushort *)packedPixel)[index]|=
5673      ((GLushort)((shoveComponents[3] * 15)+0.5)      ) & 0x000f;
5674 } /* shove4444() */
5675
5676 static void extract4444rev(int isSwap,const void *packedPixel,
5677                            GLfloat extractComponents[])
5678 {
5679    GLushort ushort;
5680
5681    if (isSwap) {
5682      ushort= __GLU_SWAP_2_BYTES(packedPixel);
5683    }
5684    else {
5685      ushort= *(const GLushort *)packedPixel;
5686    }
5687
5688    /* 00000000,00001111 == 0x000f */
5689    /* 00000000,11110000 == 0x00f0 */
5690    /* 00001111,00000000 == 0x0f00 */
5691    /* 11110000,00000000 == 0xf000 */
5692
5693    /* 15 = 2^4-1 */
5694    extractComponents[0]= (float)((ushort & 0x000F)      ) / 15.0;
5695    extractComponents[1]= (float)((ushort & 0x00F0) >>  4) / 15.0;
5696    extractComponents[2]= (float)((ushort & 0x0F00) >>  8) / 15.0;
5697    extractComponents[3]= (float)((ushort & 0xF000) >> 12) / 15.0;
5698 } /* extract4444rev() */
5699
5700 static void shove4444rev(const GLfloat shoveComponents[],
5701                          int index,void *packedPixel)
5702 {
5703    /* 00000000,00001111 == 0x000f */
5704    /* 00000000,11110000 == 0x00f0 */
5705    /* 00001111,00000000 == 0x0f00 */
5706    /* 11110000,00000000 == 0xf000 */
5707
5708    assert(0.0 <= shoveComponents[0] && shoveComponents[0] <= 1.0);
5709    assert(0.0 <= shoveComponents[1] && shoveComponents[1] <= 1.0);
5710    assert(0.0 <= shoveComponents[2] && shoveComponents[2] <= 1.0);
5711    assert(0.0 <= shoveComponents[3] && shoveComponents[3] <= 1.0);
5712
5713    /* due to limited precision, need to round before shoving */
5714    ((GLushort *)packedPixel)[index] =
5715      ((GLushort)((shoveComponents[0] * 15)+0.5)      ) & 0x000F;
5716    ((GLushort *)packedPixel)[index]|=
5717      ((GLushort)((shoveComponents[1] * 15)+0.5) <<  4) & 0x00F0;
5718    ((GLushort *)packedPixel)[index]|=
5719      ((GLushort)((shoveComponents[2] * 15)+0.5) <<  8) & 0x0F00;
5720    ((GLushort *)packedPixel)[index]|=
5721      ((GLushort)((shoveComponents[3] * 15)+0.5) << 12) & 0xF000;
5722 } /* shove4444rev() */
5723
5724 static void extract5551(int isSwap,const void *packedPixel,
5725                         GLfloat extractComponents[])
5726 {
5727    GLushort ushort;
5728
5729    if (isSwap) {
5730      ushort= __GLU_SWAP_2_BYTES(packedPixel);
5731    }
5732    else {
5733      ushort= *(const GLushort *)packedPixel;
5734    }
5735
5736    /* 11111000,00000000 == 0xf800 */
5737    /* 00000111,11000000 == 0x07c0 */
5738    /* 00000000,00111110 == 0x003e */
5739    /* 00000000,00000001 == 0x0001 */
5740
5741    extractComponents[0]=(float)((ushort & 0xf800) >> 11) / 31.0;/* 31 = 2^5-1*/
5742    extractComponents[1]=(float)((ushort & 0x07c0) >>  6) / 31.0;
5743    extractComponents[2]=(float)((ushort & 0x003e) >>  1) / 31.0;
5744    extractComponents[3]=(float)((ushort & 0x0001)      );
5745 } /* extract5551() */
5746
5747 static void shove5551(const GLfloat shoveComponents[],
5748                       int index,void *packedPixel)
5749 {
5750    /* 11111000,00000000 == 0xf800 */
5751    /* 00000111,11000000 == 0x07c0 */
5752    /* 00000000,00111110 == 0x003e */
5753    /* 00000000,00000001 == 0x0001 */
5754
5755    assert(0.0 <= shoveComponents[0] && shoveComponents[0] <= 1.0);
5756    assert(0.0 <= shoveComponents[1] && shoveComponents[1] <= 1.0);
5757    assert(0.0 <= shoveComponents[2] && shoveComponents[2] <= 1.0);
5758    assert(0.0 <= shoveComponents[3] && shoveComponents[3] <= 1.0);
5759
5760    /* due to limited precision, need to round before shoving */
5761    ((GLushort *)packedPixel)[index]  =
5762      ((GLushort)((shoveComponents[0] * 31)+0.5) << 11) & 0xf800;
5763    ((GLushort *)packedPixel)[index]|=
5764      ((GLushort)((shoveComponents[1] * 31)+0.5) <<  6) & 0x07c0;
5765    ((GLushort *)packedPixel)[index]|=
5766      ((GLushort)((shoveComponents[2] * 31)+0.5) <<  1) & 0x003e;
5767    ((GLushort *)packedPixel)[index]|=
5768      ((GLushort)((shoveComponents[3])+0.5)           ) & 0x0001;
5769 } /* shove5551() */
5770
5771 static void extract1555rev(int isSwap,const void *packedPixel,
5772                            GLfloat extractComponents[])
5773 {
5774    GLushort ushort;
5775
5776    if (isSwap) {
5777      ushort= __GLU_SWAP_2_BYTES(packedPixel);
5778    }
5779    else {
5780      ushort= *(const GLushort *)packedPixel;
5781    }
5782
5783    /* 00000000,00011111 == 0x001F */
5784    /* 00000011,11100000 == 0x03E0 */
5785    /* 01111100,00000000 == 0x7C00 */
5786    /* 10000000,00000000 == 0x8000 */
5787
5788    /* 31 = 2^5-1 */
5789    extractComponents[0]= (float)((ushort & 0x001F)      ) / 31.0;
5790    extractComponents[1]= (float)((ushort & 0x03E0) >>  5) / 31.0;
5791    extractComponents[2]= (float)((ushort & 0x7C00) >> 10) / 31.0;
5792    extractComponents[3]= (float)((ushort & 0x8000) >> 15);
5793 } /* extract1555rev() */
5794
5795 static void shove1555rev(const GLfloat shoveComponents[],
5796                          int index,void *packedPixel)
5797 {
5798    /* 00000000,00011111 == 0x001F */
5799    /* 00000011,11100000 == 0x03E0 */
5800    /* 01111100,00000000 == 0x7C00 */
5801    /* 10000000,00000000 == 0x8000 */
5802
5803    assert(0.0 <= shoveComponents[0] && shoveComponents[0] <= 1.0);
5804    assert(0.0 <= shoveComponents[1] && shoveComponents[1] <= 1.0);
5805    assert(0.0 <= shoveComponents[2] && shoveComponents[2] <= 1.0);
5806    assert(0.0 <= shoveComponents[3] && shoveComponents[3] <= 1.0);
5807
5808    /* due to limited precision, need to round before shoving */
5809    ((GLushort *)packedPixel)[index] =
5810      ((GLushort)((shoveComponents[0] * 31)+0.5)      ) & 0x001F;
5811    ((GLushort *)packedPixel)[index]|=
5812      ((GLushort)((shoveComponents[1] * 31)+0.5) <<  5) & 0x03E0;
5813    ((GLushort *)packedPixel)[index]|=
5814      ((GLushort)((shoveComponents[2] * 31)+0.5) << 10) & 0x7C00;
5815    ((GLushort *)packedPixel)[index]|=
5816      ((GLushort)((shoveComponents[3])+0.5)      << 15) & 0x8000;
5817 } /* shove1555rev() */
5818
5819 static void extract8888(int isSwap,
5820                         const void *packedPixel, GLfloat extractComponents[])
5821 {
5822    GLuint uint;
5823
5824    if (isSwap) {
5825      uint= __GLU_SWAP_4_BYTES(packedPixel);
5826    }
5827    else {
5828      uint= *(const GLuint *)packedPixel;
5829    }
5830
5831    /* 11111111,00000000,00000000,00000000 == 0xff000000 */
5832    /* 00000000,11111111,00000000,00000000 == 0x00ff0000 */
5833    /* 00000000,00000000,11111111,00000000 == 0x0000ff00 */
5834    /* 00000000,00000000,00000000,11111111 == 0x000000ff */
5835
5836    /* 255 = 2^8-1 */
5837    extractComponents[0]= (float)((uint & 0xff000000) >> 24) / 255.0;
5838    extractComponents[1]= (float)((uint & 0x00ff0000) >> 16) / 255.0;
5839    extractComponents[2]= (float)((uint & 0x0000ff00) >>  8) / 255.0;
5840    extractComponents[3]= (float)((uint & 0x000000ff)      ) / 255.0;
5841 } /* extract8888() */
5842
5843 static void shove8888(const GLfloat shoveComponents[],
5844                       int index,void *packedPixel)
5845 {
5846    /* 11111111,00000000,00000000,00000000 == 0xff000000 */
5847    /* 00000000,11111111,00000000,00000000 == 0x00ff0000 */
5848    /* 00000000,00000000,11111111,00000000 == 0x0000ff00 */
5849    /* 00000000,00000000,00000000,11111111 == 0x000000ff */
5850
5851    assert(0.0 <= shoveComponents[0] && shoveComponents[0] <= 1.0);
5852    assert(0.0 <= shoveComponents[1] && shoveComponents[1] <= 1.0);
5853    assert(0.0 <= shoveComponents[2] && shoveComponents[2] <= 1.0);
5854    assert(0.0 <= shoveComponents[3] && shoveComponents[3] <= 1.0);
5855
5856    /* due to limited precision, need to round before shoving */
5857    ((GLuint *)packedPixel)[index] =
5858      ((GLuint)((shoveComponents[0] * 255)+0.5) << 24) & 0xff000000;
5859    ((GLuint *)packedPixel)[index]|=
5860      ((GLuint)((shoveComponents[1] * 255)+0.5) << 16) & 0x00ff0000;
5861    ((GLuint *)packedPixel)[index]|=
5862      ((GLuint)((shoveComponents[2] * 255)+0.5) <<  8) & 0x0000ff00;
5863    ((GLuint *)packedPixel)[index]|=
5864      ((GLuint)((shoveComponents[3] * 255)+0.5)      ) & 0x000000ff;
5865 } /* shove8888() */
5866
5867 static void extract8888rev(int isSwap,
5868                            const void *packedPixel,GLfloat extractComponents[])
5869 {
5870    GLuint uint;
5871
5872    if (isSwap) {
5873      uint= __GLU_SWAP_4_BYTES(packedPixel);
5874    }
5875    else {
5876      uint= *(const GLuint *)packedPixel;
5877    }
5878
5879    /* 00000000,00000000,00000000,11111111 == 0x000000ff */
5880    /* 00000000,00000000,11111111,00000000 == 0x0000ff00 */
5881    /* 00000000,11111111,00000000,00000000 == 0x00ff0000 */
5882    /* 11111111,00000000,00000000,00000000 == 0xff000000 */
5883
5884    /* 255 = 2^8-1 */
5885    extractComponents[0]= (float)((uint & 0x000000FF)      ) / 255.0;
5886    extractComponents[1]= (float)((uint & 0x0000FF00) >>  8) / 255.0;
5887    extractComponents[2]= (float)((uint & 0x00FF0000) >> 16) / 255.0;
5888    extractComponents[3]= (float)((uint & 0xFF000000) >> 24) / 255.0;
5889 } /* extract8888rev() */
5890
5891 static void shove8888rev(const GLfloat shoveComponents[],
5892                          int index,void *packedPixel)
5893 {
5894    /* 00000000,00000000,00000000,11111111 == 0x000000ff */
5895    /* 00000000,00000000,11111111,00000000 == 0x0000ff00 */
5896    /* 00000000,11111111,00000000,00000000 == 0x00ff0000 */
5897    /* 11111111,00000000,00000000,00000000 == 0xff000000 */
5898
5899    assert(0.0 <= shoveComponents[0] && shoveComponents[0] <= 1.0);
5900    assert(0.0 <= shoveComponents[1] && shoveComponents[1] <= 1.0);
5901    assert(0.0 <= shoveComponents[2] && shoveComponents[2] <= 1.0);
5902    assert(0.0 <= shoveComponents[3] && shoveComponents[3] <= 1.0);
5903
5904    /* due to limited precision, need to round before shoving */
5905    ((GLuint *)packedPixel)[index] =
5906      ((GLuint)((shoveComponents[0] * 255)+0.5)      ) & 0x000000FF;
5907    ((GLuint *)packedPixel)[index]|=
5908      ((GLuint)((shoveComponents[1] * 255)+0.5) <<  8) & 0x0000FF00;
5909    ((GLuint *)packedPixel)[index]|=
5910      ((GLuint)((shoveComponents[2] * 255)+0.5) << 16) & 0x00FF0000;
5911    ((GLuint *)packedPixel)[index]|=
5912      ((GLuint)((shoveComponents[3] * 255)+0.5) << 24) & 0xFF000000;
5913 } /* shove8888rev() */
5914
5915 static void extract1010102(int isSwap,
5916                            const void *packedPixel,GLfloat extractComponents[])
5917 {
5918    GLuint uint;
5919
5920    if (isSwap) {
5921      uint= __GLU_SWAP_4_BYTES(packedPixel);
5922    }
5923    else {
5924      uint= *(const GLuint *)packedPixel;
5925    }
5926
5927    /* 11111111,11000000,00000000,00000000 == 0xffc00000 */
5928    /* 00000000,00111111,11110000,00000000 == 0x003ff000 */
5929    /* 00000000,00000000,00001111,11111100 == 0x00000ffc */
5930    /* 00000000,00000000,00000000,00000011 == 0x00000003 */
5931
5932    /* 1023 = 2^10-1 */
5933    extractComponents[0]= (float)((uint & 0xffc00000) >> 22) / 1023.0;
5934    extractComponents[1]= (float)((uint & 0x003ff000) >> 12) / 1023.0;
5935    extractComponents[2]= (float)((uint & 0x00000ffc) >>  2) / 1023.0;
5936    extractComponents[3]= (float)((uint & 0x00000003)      ) / 3.0;
5937 } /* extract1010102() */
5938
5939 static void shove1010102(const GLfloat shoveComponents[],
5940                          int index,void *packedPixel)
5941 {
5942    /* 11111111,11000000,00000000,00000000 == 0xffc00000 */
5943    /* 00000000,00111111,11110000,00000000 == 0x003ff000 */
5944    /* 00000000,00000000,00001111,11111100 == 0x00000ffc */
5945    /* 00000000,00000000,00000000,00000011 == 0x00000003 */
5946
5947    assert(0.0 <= shoveComponents[0] && shoveComponents[0] <= 1.0);
5948    assert(0.0 <= shoveComponents[1] && shoveComponents[1] <= 1.0);
5949    assert(0.0 <= shoveComponents[2] && shoveComponents[2] <= 1.0);
5950    assert(0.0 <= shoveComponents[3] && shoveComponents[3] <= 1.0);
5951
5952    /* due to limited precision, need to round before shoving */
5953    ((GLuint *)packedPixel)[index] =
5954      ((GLuint)((shoveComponents[0] * 1023)+0.5) << 22) & 0xffc00000;
5955    ((GLuint *)packedPixel)[index]|=
5956      ((GLuint)((shoveComponents[1] * 1023)+0.5) << 12) & 0x003ff000;
5957    ((GLuint *)packedPixel)[index]|=
5958      ((GLuint)((shoveComponents[2] * 1023)+0.5) <<  2) & 0x00000ffc;
5959    ((GLuint *)packedPixel)[index]|=
5960      ((GLuint)((shoveComponents[3] * 3)+0.5)         ) & 0x00000003;
5961 } /* shove1010102() */
5962
5963 static void extract2101010rev(int isSwap,
5964                               const void *packedPixel,
5965                               GLfloat extractComponents[])
5966 {
5967    GLuint uint;
5968
5969    if (isSwap) {
5970      uint= __GLU_SWAP_4_BYTES(packedPixel);
5971    }
5972    else {
5973      uint= *(const GLuint *)packedPixel;
5974    }
5975
5976    /* 00000000,00000000,00000011,11111111 == 0x000003FF */
5977    /* 00000000,00001111,11111100,00000000 == 0x000FFC00 */
5978    /* 00111111,11110000,00000000,00000000 == 0x3FF00000 */
5979    /* 11000000,00000000,00000000,00000000 == 0xC0000000 */
5980
5981    /* 1023 = 2^10-1 */
5982    extractComponents[0]= (float)((uint & 0x000003FF)      ) / 1023.0;
5983    extractComponents[1]= (float)((uint & 0x000FFC00) >> 10) / 1023.0;
5984    extractComponents[2]= (float)((uint & 0x3FF00000) >> 20) / 1023.0;
5985    extractComponents[3]= (float)((uint & 0xC0000000) >> 30) / 3.0;
5986    /* 3 = 2^2-1 */
5987 } /* extract2101010rev() */
5988
5989 static void shove2101010rev(const GLfloat shoveComponents[],
5990                             int index,void *packedPixel)
5991 {
5992    /* 00000000,00000000,00000011,11111111 == 0x000003FF */
5993    /* 00000000,00001111,11111100,00000000 == 0x000FFC00 */
5994    /* 00111111,11110000,00000000,00000000 == 0x3FF00000 */
5995    /* 11000000,00000000,00000000,00000000 == 0xC0000000 */
5996
5997    assert(0.0 <= shoveComponents[0] && shoveComponents[0] <= 1.0);
5998    assert(0.0 <= shoveComponents[1] && shoveComponents[1] <= 1.0);
5999    assert(0.0 <= shoveComponents[2] && shoveComponents[2] <= 1.0);
6000    assert(0.0 <= shoveComponents[3] && shoveComponents[3] <= 1.0);
6001
6002    /* due to limited precision, need to round before shoving */
6003    ((GLuint *)packedPixel)[index] =
6004      ((GLuint)((shoveComponents[0] * 1023)+0.5)      ) & 0x000003FF;
6005    ((GLuint *)packedPixel)[index]|=
6006      ((GLuint)((shoveComponents[1] * 1023)+0.5) << 10) & 0x000FFC00;
6007    ((GLuint *)packedPixel)[index]|=
6008      ((GLuint)((shoveComponents[2] * 1023)+0.5) << 20) & 0x3FF00000;
6009    ((GLuint *)packedPixel)[index]|=
6010      ((GLuint)((shoveComponents[3] * 3)+0.5)    << 30) & 0xC0000000;
6011 } /* shove2101010rev() */
6012
6013 static void scaleInternalPackedPixel(int components,
6014                                      void (*extractPackedPixel)
6015                                      (int, const void *,GLfloat []),
6016                                      void (*shovePackedPixel)
6017                                      (const GLfloat [], int, void *),
6018                                      GLint widthIn,GLint heightIn,
6019                                      const void *dataIn,
6020                                      GLint widthOut,GLint heightOut,
6021                                      void *dataOut,
6022                                      GLint pixelSizeInBytes,
6023                                      GLint rowSizeInBytes,GLint isSwap)
6024 {
6025     float convx;
6026     float convy;
6027     float percent;
6028
6029     /* Max components in a format is 4, so... */
6030     float totals[4];
6031     float extractTotals[4], extractMoreTotals[4], shoveTotals[4];
6032
6033     float area;
6034     int i,j,k,xindex;
6035
6036     const char *temp, *temp0;
6037     int outindex;
6038
6039     int lowx_int, highx_int, lowy_int, highy_int;
6040     float x_percent, y_percent;
6041     float lowx_float, highx_float, lowy_float, highy_float;
6042     float convy_float, convx_float;
6043     int convy_int, convx_int;
6044     int l, m;
6045     const char *left, *right;
6046
6047     if (widthIn == widthOut*2 && heightIn == heightOut*2) {
6048         halveImagePackedPixel(components,extractPackedPixel,shovePackedPixel,
6049                               widthIn, heightIn, dataIn, dataOut,
6050                               pixelSizeInBytes,rowSizeInBytes,isSwap);
6051         return;
6052     }
6053     convy = (float) heightIn/heightOut;
6054     convx = (float) widthIn/widthOut;
6055     convy_int = floor(convy);
6056     convy_float = convy - convy_int;
6057     convx_int = floor(convx);
6058     convx_float = convx - convx_int;
6059
6060     area = convx * convy;
6061
6062     lowy_int = 0;
6063     lowy_float = 0;
6064     highy_int = convy_int;
6065     highy_float = convy_float;
6066
6067     for (i = 0; i < heightOut; i++) {
6068         lowx_int = 0;
6069         lowx_float = 0;
6070         highx_int = convx_int;
6071         highx_float = convx_float;
6072
6073         for (j = 0; j < widthOut; j++) {
6074             /*
6075             ** Ok, now apply box filter to box that goes from (lowx, lowy)
6076             ** to (highx, highy) on input data into this pixel on output
6077             ** data.
6078             */
6079             totals[0] = totals[1] = totals[2] = totals[3] = 0.0;
6080
6081             /* calculate the value for pixels in the 1st row */
6082             xindex = lowx_int*pixelSizeInBytes;
6083             if((highy_int>lowy_int) && (highx_int>lowx_int)) {
6084
6085                 y_percent = 1-lowy_float;
6086                 temp = (const char *)dataIn + xindex + lowy_int * rowSizeInBytes;
6087                 percent = y_percent * (1-lowx_float);
6088 #if 0
6089                 for (k = 0, temp_index = temp; k < components;
6090                      k++, temp_index += element_size) {
6091                     if (myswap_bytes) {
6092                         totals[k] += __GLU_SWAP_2_BYTES(temp_index) * percent;
6093                     } else {
6094                         totals[k] += *(const GLushort*)temp_index * percent;
6095                     }
6096                 }
6097 #else
6098                 (*extractPackedPixel)(isSwap,temp,extractTotals);
6099                 for (k = 0; k < components; k++) {
6100                    totals[k]+= extractTotals[k] * percent;
6101                 }
6102 #endif
6103                 left = temp;
6104                 for(l = lowx_int+1; l < highx_int; l++) {
6105                     temp += pixelSizeInBytes;
6106 #if 0
6107                     for (k = 0, temp_index = temp; k < components;
6108                          k++, temp_index += element_size) {
6109                         if (myswap_bytes) {
6110                             totals[k] +=
6111                                  __GLU_SWAP_2_BYTES(temp_index) * y_percent;
6112                         } else {
6113                             totals[k] += *(const GLushort*)temp_index * y_percent;
6114                         }
6115                     }
6116 #else
6117                     (*extractPackedPixel)(isSwap,temp,extractTotals);
6118                     for (k = 0; k < components; k++) {
6119                        totals[k]+= extractTotals[k] * y_percent;
6120                     }
6121 #endif
6122                 }
6123                 temp += pixelSizeInBytes;
6124                 right = temp;
6125                 percent = y_percent * highx_float;
6126 #if 0
6127                 for (k = 0, temp_index = temp; k < components;
6128                      k++, temp_index += element_size) {
6129                     if (myswap_bytes) {
6130                         totals[k] += __GLU_SWAP_2_BYTES(temp_index) * percent;
6131                     } else {
6132                         totals[k] += *(const GLushort*)temp_index * percent;
6133                     }
6134                 }
6135 #else
6136                 (*extractPackedPixel)(isSwap,temp,extractTotals);
6137                 for (k = 0; k < components; k++) {
6138                    totals[k]+= extractTotals[k] * percent;
6139                 }
6140 #endif
6141
6142                 /* calculate the value for pixels in the last row */
6143                 
6144                 y_percent = highy_float;
6145                 percent = y_percent * (1-lowx_float);
6146                 temp = (const char *)dataIn + xindex + highy_int * rowSizeInBytes;
6147 #if 0
6148                 for (k = 0, temp_index = temp; k < components;
6149                      k++, temp_index += element_size) {
6150                     if (myswap_bytes) {
6151                         totals[k] += __GLU_SWAP_2_BYTES(temp_index) * percent;
6152                     } else {
6153                         totals[k] += *(const GLushort*)temp_index * percent;
6154                     }
6155                 }
6156 #else
6157                 (*extractPackedPixel)(isSwap,temp,extractTotals);
6158                 for (k = 0; k < components; k++) {
6159                    totals[k]+= extractTotals[k] * percent;
6160                 }
6161 #endif
6162                 for(l = lowx_int+1; l < highx_int; l++) {
6163                     temp += pixelSizeInBytes;
6164 #if 0
6165                     for (k = 0, temp_index = temp; k < components;
6166                          k++, temp_index += element_size) {
6167                         if (myswap_bytes) {
6168                             totals[k] +=
6169                                  __GLU_SWAP_2_BYTES(temp_index) * y_percent;
6170                         } else {
6171                             totals[k] += *(const GLushort*)temp_index * y_percent;
6172                         }
6173                     }
6174 #else
6175                     (*extractPackedPixel)(isSwap,temp,extractTotals);
6176                     for (k = 0; k < components; k++) {
6177                        totals[k]+= extractTotals[k] * y_percent;
6178                     }
6179 #endif
6180
6181                 }
6182                 temp += pixelSizeInBytes;
6183                 percent = y_percent * highx_float;
6184 #if 0
6185                 for (k = 0, temp_index = temp; k < components;
6186                      k++, temp_index += element_size) {
6187                     if (myswap_bytes) {
6188                         totals[k] += __GLU_SWAP_2_BYTES(temp_index) * percent;
6189                     } else {
6190                         totals[k] += *(const GLushort*)temp_index * percent;
6191                     }
6192                 }
6193 #else
6194                 (*extractPackedPixel)(isSwap,temp,extractTotals);
6195                 for (k = 0; k < components; k++) {
6196                    totals[k]+= extractTotals[k] * percent;
6197                 }
6198 #endif
6199
6200                 /* calculate the value for pixels in the 1st and last column */
6201                 for(m = lowy_int+1; m < highy_int; m++) {
6202                     left += rowSizeInBytes;
6203                     right += rowSizeInBytes;
6204 #if 0
6205                     for (k = 0; k < components;
6206                          k++, left += element_size, right += element_size) {
6207                         if (myswap_bytes) {
6208                             totals[k] +=
6209                                 __GLU_SWAP_2_BYTES(left) * (1-lowx_float) +
6210                                 __GLU_SWAP_2_BYTES(right) * highx_float;
6211                         } else {
6212                             totals[k] += *(const GLushort*)left * (1-lowx_float)
6213                                        + *(const GLushort*)right * highx_float;
6214                         }
6215                     }
6216 #else
6217                     (*extractPackedPixel)(isSwap,left,extractTotals);
6218                     (*extractPackedPixel)(isSwap,right,extractMoreTotals);
6219                     for (k = 0; k < components; k++) {
6220                        totals[k]+= (extractTotals[k]*(1-lowx_float) +
6221                                    extractMoreTotals[k]*highx_float);
6222                     }
6223 #endif
6224                 }
6225             } else if (highy_int > lowy_int) {
6226                 x_percent = highx_float - lowx_float;
6227                 percent = (1-lowy_float)*x_percent;
6228                 temp = (const char *)dataIn + xindex + lowy_int*rowSizeInBytes;
6229 #if 0
6230                 for (k = 0, temp_index = temp; k < components;
6231                      k++, temp_index += element_size) {
6232                     if (myswap_bytes) {
6233                         totals[k] += __GLU_SWAP_2_BYTES(temp_index) * percent;
6234                     } else {
6235                         totals[k] += *(const GLushort*)temp_index * percent;
6236                     }
6237                 }
6238 #else
6239                 (*extractPackedPixel)(isSwap,temp,extractTotals);
6240                 for (k = 0; k < components; k++) {
6241                    totals[k]+= extractTotals[k] * percent;
6242                 }
6243 #endif
6244                 for(m = lowy_int+1; m < highy_int; m++) {
6245                     temp += rowSizeInBytes;
6246 #if 0
6247                     for (k = 0, temp_index = temp; k < components;
6248                          k++, temp_index += element_size) {
6249                         if (myswap_bytes) {
6250                             totals[k] +=
6251                                 __GLU_SWAP_2_BYTES(temp_index) * x_percent;
6252                         } else {
6253                             totals[k] += *(const GLushort*)temp_index * x_percent;
6254                         }
6255                     }
6256 #else
6257                     (*extractPackedPixel)(isSwap,temp,extractTotals);
6258                     for (k = 0; k < components; k++) {
6259                        totals[k]+= extractTotals[k] * x_percent;
6260                     }
6261 #endif
6262                 }
6263                 percent = x_percent * highy_float;
6264                 temp += rowSizeInBytes;
6265 #if 0
6266                 for (k = 0, temp_index = temp; k < components;
6267                      k++, temp_index += element_size) {
6268                     if (myswap_bytes) {
6269                         totals[k] += __GLU_SWAP_2_BYTES(temp_index) * percent;
6270                     } else {
6271                         totals[k] += *(const GLushort*)temp_index * percent;
6272                     }
6273                 }
6274 #else
6275                 (*extractPackedPixel)(isSwap,temp,extractTotals);
6276                 for (k = 0; k < components; k++) {
6277                    totals[k]+= extractTotals[k] * percent;
6278                 }
6279 #endif
6280             } else if (highx_int > lowx_int) {
6281                 y_percent = highy_float - lowy_float;
6282                 percent = (1-lowx_float)*y_percent;
6283                 temp = (const char *)dataIn + xindex + lowy_int*rowSizeInBytes;
6284 #if 0
6285                 for (k = 0, temp_index = temp; k < components;
6286                      k++, temp_index += element_size) {
6287                     if (myswap_bytes) {
6288                         totals[k] += __GLU_SWAP_2_BYTES(temp_index) * percent;
6289                     } else {
6290                         totals[k] += *(const GLushort*)temp_index * percent;
6291                     }
6292                 }
6293 #else
6294                 (*extractPackedPixel)(isSwap,temp,extractTotals);
6295                 for (k = 0; k < components; k++) {
6296                    totals[k]+= extractTotals[k] * percent;
6297                 }
6298 #endif
6299                 for (l = lowx_int+1; l < highx_int; l++) {
6300                     temp += pixelSizeInBytes;
6301 #if 0
6302                     for (k = 0, temp_index = temp; k < components;
6303                          k++, temp_index += element_size) {
6304                         if (myswap_bytes) {
6305                             totals[k] +=
6306                                 __GLU_SWAP_2_BYTES(temp_index) * y_percent;
6307                         } else {
6308                             totals[k] += *(const GLushort*)temp_index * y_percent;
6309                         }
6310                     }
6311 #else
6312                 (*extractPackedPixel)(isSwap,temp,extractTotals);
6313                 for (k = 0; k < components; k++) {
6314                    totals[k]+= extractTotals[k] * y_percent;
6315                 }
6316 #endif
6317                 }
6318                 temp += pixelSizeInBytes;
6319                 percent = y_percent * highx_float;
6320 #if 0
6321                 for (k = 0, temp_index = temp; k < components;
6322                      k++, temp_index += element_size) {
6323                     if (myswap_bytes) {
6324                         totals[k] += __GLU_SWAP_2_BYTES(temp_index) * percent;
6325                     } else {
6326                         totals[k] += *(const GLushort*)temp_index * percent;
6327                     }
6328                 }
6329 #else
6330                 (*extractPackedPixel)(isSwap,temp,extractTotals);
6331                 for (k = 0; k < components; k++) {
6332                    totals[k]+= extractTotals[k] * percent;
6333                 }
6334 #endif
6335             } else {
6336                 percent = (highy_float-lowy_float)*(highx_float-lowx_float);
6337                 temp = (const char *)dataIn + xindex + lowy_int * rowSizeInBytes;
6338 #if 0
6339                 for (k = 0, temp_index = temp; k < components;
6340                      k++, temp_index += element_size) {
6341                     if (myswap_bytes) {
6342                         totals[k] += __GLU_SWAP_2_BYTES(temp_index) * percent;
6343                     } else {
6344                         totals[k] += *(const GLushort*)temp_index * percent;
6345                     }
6346                 }
6347 #else
6348                 (*extractPackedPixel)(isSwap,temp,extractTotals);
6349                 for (k = 0; k < components; k++) {
6350                    totals[k]+= extractTotals[k] * percent;
6351                 }
6352 #endif
6353             }
6354
6355             /* this is for the pixels in the body */
6356             temp0 = (const char *)dataIn + xindex + pixelSizeInBytes + (lowy_int+1)*rowSizeInBytes;
6357             for (m = lowy_int+1; m < highy_int; m++) {
6358                 temp = temp0;
6359                 for(l = lowx_int+1; l < highx_int; l++) {
6360 #if 0
6361                     for (k = 0, temp_index = temp; k < components;
6362                          k++, temp_index += element_size) {
6363                         if (myswap_bytes) {
6364                             totals[k] += __GLU_SWAP_2_BYTES(temp_index);
6365                         } else {
6366                             totals[k] += *(const GLushort*)temp_index;
6367                         }
6368                     }
6369 #else
6370                     (*extractPackedPixel)(isSwap,temp,extractTotals);
6371                     for (k = 0; k < components; k++) {
6372                        totals[k]+= extractTotals[k];
6373                     }
6374 #endif
6375                     temp += pixelSizeInBytes;
6376                 }
6377                 temp0 += rowSizeInBytes;
6378             }
6379
6380             outindex = (j + (i * widthOut)); /* * (components == 1) */
6381 #if 0
6382             for (k = 0; k < components; k++) {
6383                 dataout[outindex + k] = totals[k]/area;
6384                 /*printf("totals[%d] = %f\n", k, totals[k]);*/
6385             }
6386 #else
6387             for (k = 0; k < components; k++) {
6388                 shoveTotals[k]= totals[k]/area;
6389             }
6390             (*shovePackedPixel)(shoveTotals,outindex,(void *)dataOut);
6391 #endif
6392             lowx_int = highx_int;
6393             lowx_float = highx_float;
6394             highx_int += convx_int;
6395             highx_float += convx_float;
6396             if(highx_float > 1) {
6397                 highx_float -= 1.0;
6398                 highx_int++;
6399             }
6400         }
6401         lowy_int = highy_int;
6402         lowy_float = highy_float;
6403         highy_int += convy_int;
6404         highy_float += convy_float;
6405         if(highy_float > 1) {
6406             highy_float -= 1.0;
6407             highy_int++;
6408         }
6409     }
6410
6411     assert(outindex == (widthOut*heightOut - 1));
6412 } /* scaleInternalPackedPixel() */
6413
6414 /* rowSizeInBytes is at least the width (in bytes) due to padding on
6415  *  inputs; not always equal. Output NEVER has row padding.
6416  */
6417 static void halveImagePackedPixel(int components,
6418                                   void (*extractPackedPixel)
6419                                   (int, const void *,GLfloat []),
6420                                   void (*shovePackedPixel)
6421                                   (const GLfloat [],int, void *),
6422                                   GLint width, GLint height,
6423                                   const void *dataIn, void *dataOut,
6424                                   GLint pixelSizeInBytes,
6425                                   GLint rowSizeInBytes, GLint isSwap)
6426 {
6427    /* handle case where there is only 1 column/row */
6428    if (width == 1 || height == 1) {
6429       assert(!(width == 1 && height == 1)); /* can't be 1x1 */
6430       halve1DimagePackedPixel(components,extractPackedPixel,shovePackedPixel,
6431                               width,height,dataIn,dataOut,pixelSizeInBytes,
6432                               rowSizeInBytes,isSwap);
6433       return;
6434    }
6435
6436    {
6437       int ii, jj;
6438
6439       int halfWidth= width / 2;
6440       int halfHeight= height / 2;
6441       const char *src= (const char *) dataIn;
6442       int padBytes= rowSizeInBytes - (width*pixelSizeInBytes);
6443       int outIndex= 0;
6444
6445       for (ii= 0; ii< halfHeight; ii++) {
6446          for (jj= 0; jj< halfWidth; jj++) {
6447 #define BOX4 4
6448             float totals[4];    /* 4 is maximum components */
6449             float extractTotals[BOX4][4]; /* 4 is maximum components */
6450             int cc;
6451
6452             (*extractPackedPixel)(isSwap,src,
6453                                   &extractTotals[0][0]);
6454             (*extractPackedPixel)(isSwap,(src+pixelSizeInBytes),
6455                                   &extractTotals[1][0]);
6456             (*extractPackedPixel)(isSwap,(src+rowSizeInBytes),
6457                                   &extractTotals[2][0]);
6458             (*extractPackedPixel)(isSwap,
6459                                   (src+rowSizeInBytes+pixelSizeInBytes),
6460                                   &extractTotals[3][0]);
6461             for (cc = 0; cc < components; cc++) {
6462                int kk;
6463
6464                /* grab 4 pixels to average */
6465                totals[cc]= 0.0;
6466                /* totals[RED]= extractTotals[0][RED]+extractTotals[1][RED]+
6467                 *              extractTotals[2][RED]+extractTotals[3][RED];
6468                 * totals[RED]/= 4.0;
6469                 */
6470                for (kk = 0; kk < BOX4; kk++) {
6471                   totals[cc]+= extractTotals[kk][cc];
6472                }
6473                totals[cc]/= (float)BOX4;
6474             }
6475             (*shovePackedPixel)(totals,outIndex,dataOut);
6476
6477             outIndex++;
6478             /* skip over to next square of 4 */
6479             src+= pixelSizeInBytes + pixelSizeInBytes;
6480          }
6481          /* skip past pad bytes, if any, to get to next row */
6482          src+= padBytes;
6483
6484          /* src is at beginning of a row here, but it's the second row of
6485           * the square block of 4 pixels that we just worked on so we
6486           * need to go one more row.
6487           * i.e.,
6488           *                   OO...
6489           *           here -->OO...
6490           *       but want -->OO...
6491           *                   OO...
6492           *                   ...
6493           */
6494          src+= rowSizeInBytes;
6495       }
6496
6497       /* both pointers must reach one byte after the end */
6498       assert(src == &((const char *)dataIn)[rowSizeInBytes*height]);
6499       assert(outIndex == halfWidth * halfHeight);
6500    }
6501 } /* halveImagePackedPixel() */
6502
6503 static void halve1DimagePackedPixel(int components,
6504                                     void (*extractPackedPixel)
6505                                     (int, const void *,GLfloat []),
6506                                     void (*shovePackedPixel)
6507                                     (const GLfloat [],int, void *),
6508                                     GLint width, GLint height,
6509                                     const void *dataIn, void *dataOut,
6510                                     GLint pixelSizeInBytes,
6511                                     GLint rowSizeInBytes, GLint isSwap)
6512 {
6513    int halfWidth= width / 2;
6514    int halfHeight= height / 2;
6515    const char *src= (const char *) dataIn;
6516    int jj;
6517
6518    assert(width == 1 || height == 1); /* must be 1D */
6519    assert(width != height);     /* can't be square */
6520
6521    if (height == 1) {   /* 1 row */
6522       int outIndex= 0;
6523
6524       assert(width != 1);       /* widthxheight can't be 1x1 */
6525       halfHeight= 1;
6526
6527       /* one horizontal row with possible pad bytes */
6528
6529       for (jj= 0; jj< halfWidth; jj++) {
6530 #define BOX2 2
6531          float totals[4];       /* 4 is maximum components */
6532          float extractTotals[BOX2][4]; /* 4 is maximum components */
6533          int cc;
6534
6535          /* average two at a time, instead of four */
6536          (*extractPackedPixel)(isSwap,src,
6537                                &extractTotals[0][0]);
6538          (*extractPackedPixel)(isSwap,(src+pixelSizeInBytes),
6539                                &extractTotals[1][0]);                   
6540          for (cc = 0; cc < components; cc++) {
6541             int kk;
6542
6543             /* grab 2 pixels to average */
6544             totals[cc]= 0.0;
6545             /* totals[RED]= extractTotals[0][RED]+extractTotals[1][RED];
6546              * totals[RED]/= 2.0;
6547              */
6548             for (kk = 0; kk < BOX2; kk++) {
6549                totals[cc]+= extractTotals[kk][cc];
6550             }
6551             totals[cc]/= (float)BOX2;
6552          }
6553          (*shovePackedPixel)(totals,outIndex,dataOut);
6554
6555          outIndex++;
6556          /* skip over to next group of 2 */
6557          src+= pixelSizeInBytes + pixelSizeInBytes;
6558       }
6559
6560       {
6561          int padBytes= rowSizeInBytes - (width*pixelSizeInBytes);
6562          src+= padBytes;        /* for assertion only */
6563       }
6564       assert(src == &((const char *)dataIn)[rowSizeInBytes]);
6565       assert(outIndex == halfWidth * halfHeight);
6566    }
6567    else if (width == 1) { /* 1 column */
6568       int outIndex= 0;
6569
6570       assert(height != 1);      /* widthxheight can't be 1x1 */
6571       halfWidth= 1;
6572       /* one vertical column with possible pad bytes per row */
6573       /* average two at a time */
6574
6575       for (jj= 0; jj< halfHeight; jj++) {
6576 #define BOX2 2
6577          float totals[4];       /* 4 is maximum components */
6578          float extractTotals[BOX2][4]; /* 4 is maximum components */
6579          int cc;
6580
6581          /* average two at a time, instead of four */
6582          (*extractPackedPixel)(isSwap,src,
6583                                &extractTotals[0][0]);
6584          (*extractPackedPixel)(isSwap,(src+rowSizeInBytes),
6585                                &extractTotals[1][0]);                   
6586          for (cc = 0; cc < components; cc++) {
6587             int kk;
6588
6589             /* grab 2 pixels to average */
6590             totals[cc]= 0.0;
6591             /* totals[RED]= extractTotals[0][RED]+extractTotals[1][RED];
6592              * totals[RED]/= 2.0;
6593              */
6594             for (kk = 0; kk < BOX2; kk++) {
6595                totals[cc]+= extractTotals[kk][cc];
6596             }
6597             totals[cc]/= (float)BOX2;
6598          }
6599          (*shovePackedPixel)(totals,outIndex,dataOut);
6600
6601          outIndex++;
6602          src+= rowSizeInBytes + rowSizeInBytes; /* go to row after next */
6603       }
6604
6605       assert(src == &((const char *)dataIn)[rowSizeInBytes*height]);
6606       assert(outIndex == halfWidth * halfHeight);
6607    }
6608 } /* halve1DimagePackedPixel() */
6609
6610 /*===========================================================================*/
6611
6612 #ifdef RESOLVE_3D_TEXTURE_SUPPORT
6613 /*
6614  * This section ensures that GLU 1.3 will load and run on
6615  * a GL 1.1 implementation. It dynamically resolves the
6616  * call to glTexImage3D() which might not be available.
6617  * Or is it might be supported as an extension.
6618  * Contributed by Gerk Huisma <gerk@five-d.demon.nl>.
6619  */
6620
6621 typedef void (GLAPIENTRY *TexImage3Dproc)( GLenum target, GLint level,
6622                                                  GLenum internalFormat,
6623                                                  GLsizei width, GLsizei height,
6624                                                  GLsizei depth, GLint border,
6625                                                  GLenum format, GLenum type,
6626                                                  const GLvoid *pixels );
6627
6628 static TexImage3Dproc pTexImage3D = 0;
6629
6630 #if !defined(_WIN32) && !defined(__WIN32__)
6631 #  include <dlfcn.h>
6632 #  include <sys/types.h>
6633 #else
6634   WINGDIAPI PROC  WINAPI wglGetProcAddress(LPCSTR);
6635 #endif
6636
6637 static void gluTexImage3D( GLenum target, GLint level,
6638                            GLenum internalFormat,
6639                            GLsizei width, GLsizei height,
6640                            GLsizei depth, GLint border,
6641                            GLenum format, GLenum type,
6642                            const GLvoid *pixels )
6643 {
6644    if (!pTexImage3D) {
6645 #if defined(_WIN32) || defined(__WIN32__)
6646       pTexImage3D = (TexImage3Dproc) wglGetProcAddress("glTexImage3D");
6647       if (!pTexImage3D)
6648          pTexImage3D = (TexImage3Dproc) wglGetProcAddress("glTexImage3DEXT");
6649 #else
6650       void *libHandle = dlopen("libgl.so", RTLD_LAZY);
6651       pTexImage3D = (TexImage3Dproc) dlsym(libHandle, "glTexImage3D" );
6652       if (!pTexImage3D)
6653          pTexImage3D = (TexImage3Dproc) dlsym(libHandle,"glTexImage3DEXT");
6654       dlclose(libHandle);
6655 #endif
6656    }
6657
6658    /* Now call glTexImage3D */
6659    if (pTexImage3D)
6660       pTexImage3D(target, level, internalFormat, width, height,
6661                   depth, border, format, type, pixels);
6662 }
6663
6664 #else
6665
6666 /* Only bind to a GL 1.2 implementation: */
6667 #define gluTexImage3D glTexImage3D
6668
6669 #endif
6670
6671 static GLint imageSize3D(GLint width, GLint height, GLint depth,
6672                          GLenum format, GLenum type)
6673 {
6674     int components= elements_per_group(format,type);
6675     int bytes_per_row=  bytes_per_element(type) * width;
6676
6677 assert(width > 0 && height > 0 && depth > 0);
6678 assert(type != GL_BITMAP);
6679
6680     return bytes_per_row * height * depth * components;
6681 } /* imageSize3D() */
6682
6683 static void fillImage3D(const PixelStorageModes *psm,
6684                         GLint width, GLint height, GLint depth, GLenum format,
6685                         GLenum type, GLboolean indexFormat,
6686                         const void *userImage, GLushort *newImage)
6687 {
6688    int myswapBytes;
6689    int components;
6690    int groupsPerLine;
6691    int elementSize;
6692    int groupSize;
6693    int rowSize;
6694    int padding;
6695    int elementsPerLine;
6696    int rowsPerImage;
6697    int imageSize;
6698    const GLubyte *start, *rowStart, *iter;
6699    GLushort *iter2;
6700    int ww, hh, dd, k;
6701
6702    myswapBytes= psm->unpack_swap_bytes;
6703    components= elements_per_group(format,type);
6704    if (psm->unpack_row_length > 0) {
6705       groupsPerLine= psm->unpack_row_length;
6706    }
6707    else {
6708       groupsPerLine= width;
6709    }
6710    elementSize= bytes_per_element(type);
6711    groupSize= elementSize * components;
6712    if (elementSize == 1) myswapBytes= 0;
6713
6714    /* 3dstuff begin */
6715    if (psm->unpack_image_height > 0) {
6716       rowsPerImage= psm->unpack_image_height;
6717    }
6718    else {
6719       rowsPerImage= height;
6720    }
6721    /* 3dstuff end */
6722
6723    rowSize= groupsPerLine * groupSize;
6724    padding= rowSize % psm->unpack_alignment;
6725    if (padding) {
6726       rowSize+= psm->unpack_alignment - padding;
6727    }
6728
6729    imageSize= rowsPerImage * rowSize; /* 3dstuff */
6730
6731    start= (const GLubyte *)userImage + psm->unpack_skip_rows * rowSize +
6732                                  psm->unpack_skip_pixels * groupSize +
6733                                  /*3dstuff*/
6734                                  psm->unpack_skip_images * imageSize;
6735    elementsPerLine = width * components;
6736
6737    iter2= newImage;
6738    for (dd= 0; dd < depth; dd++) {
6739       rowStart= start;
6740
6741       for (hh= 0; hh < height; hh++) {
6742          iter= rowStart;
6743
6744          for (ww= 0; ww < elementsPerLine; ww++) {
6745             Type_Widget widget;
6746             float extractComponents[4];
6747
6748             switch(type) {
6749             case GL_UNSIGNED_BYTE:
6750               if (indexFormat) {
6751                   *iter2++ = *iter;
6752               } else {
6753                   *iter2++ = (*iter) * 257;
6754               }
6755               break;
6756             case GL_BYTE:
6757               if (indexFormat) {
6758                   *iter2++ = *((const GLbyte *) iter);
6759               } else {
6760                   /* rough approx */
6761                   *iter2++ = (*((const GLbyte *) iter)) * 516;
6762               }
6763               break;
6764             case GL_UNSIGNED_BYTE_3_3_2:
6765               extract332(0,iter,extractComponents);
6766               for (k = 0; k < 3; k++) {
6767                 *iter2++ = (GLushort)(extractComponents[k]*65535);
6768               }
6769               break;
6770             case GL_UNSIGNED_BYTE_2_3_3_REV:
6771               extract233rev(0,iter,extractComponents);
6772               for (k = 0; k < 3; k++) {
6773                 *iter2++ = (GLushort)(extractComponents[k]*65535);
6774               }
6775               break;
6776             case GL_UNSIGNED_SHORT_5_6_5:                               
6777               extract565(myswapBytes,iter,extractComponents);
6778               for (k = 0; k < 3; k++) {
6779                 *iter2++ = (GLushort)(extractComponents[k]*65535);
6780               }
6781               break;
6782             case GL_UNSIGNED_SHORT_5_6_5_REV:                           
6783               extract565rev(myswapBytes,iter,extractComponents);
6784               for (k = 0; k < 3; k++) {
6785                 *iter2++ = (GLushort)(extractComponents[k]*65535);
6786               }
6787               break;
6788             case GL_UNSIGNED_SHORT_4_4_4_4:             
6789               extract4444(myswapBytes,iter,extractComponents);
6790               for (k = 0; k < 4; k++) {
6791                 *iter2++ = (GLushort)(extractComponents[k]*65535);
6792               }
6793               break;
6794             case GL_UNSIGNED_SHORT_4_4_4_4_REV:         
6795               extract4444rev(myswapBytes,iter,extractComponents);
6796               for (k = 0; k < 4; k++) {
6797                 *iter2++ = (GLushort)(extractComponents[k]*65535);
6798               }
6799               break;
6800             case GL_UNSIGNED_SHORT_5_5_5_1:             
6801               extract5551(myswapBytes,iter,extractComponents);
6802               for (k = 0; k < 4; k++) {
6803                 *iter2++ = (GLushort)(extractComponents[k]*65535);
6804               }
6805               break;
6806             case GL_UNSIGNED_SHORT_1_5_5_5_REV:
6807               extract1555rev(myswapBytes,iter,extractComponents);
6808               for (k = 0; k < 4; k++) {
6809                 *iter2++ = (GLushort)(extractComponents[k]*65535);
6810               }
6811               break;
6812             case GL_UNSIGNED_SHORT:
6813             case GL_SHORT:
6814               if (myswapBytes) {
6815                   widget.ub[0] = iter[1];
6816                   widget.ub[1] = iter[0];
6817               } else {
6818                   widget.ub[0] = iter[0];
6819                   widget.ub[1] = iter[1];
6820               }
6821               if (type == GL_SHORT) {
6822                   if (indexFormat) {
6823                       *iter2++ = widget.s[0];
6824                   } else {
6825                       /* rough approx */
6826                       *iter2++ = widget.s[0]*2;
6827                   }
6828               } else {
6829                   *iter2++ = widget.us[0];
6830               }
6831               break;
6832             case GL_UNSIGNED_INT_8_8_8_8:               
6833               extract8888(myswapBytes,iter,extractComponents);
6834               for (k = 0; k < 4; k++) {
6835                 *iter2++ = (GLushort)(extractComponents[k]*65535);
6836               }
6837               break;
6838             case GL_UNSIGNED_INT_8_8_8_8_REV:           
6839               extract8888rev(myswapBytes,iter,extractComponents);
6840               for (k = 0; k < 4; k++) {
6841                 *iter2++ = (GLushort)(extractComponents[k]*65535);
6842               }
6843               break;
6844             case GL_UNSIGNED_INT_10_10_10_2:            
6845               extract1010102(myswapBytes,iter,extractComponents);
6846               for (k = 0; k < 4; k++) {
6847                 *iter2++ = (GLushort)(extractComponents[k]*65535);
6848               }
6849               break;
6850             case GL_UNSIGNED_INT_2_10_10_10_REV:
6851               extract2101010rev(myswapBytes,iter,extractComponents);
6852               for (k = 0; k < 4; k++) {
6853                 *iter2++ = (GLushort)(extractComponents[k]*65535);
6854               }
6855               break;
6856             case GL_INT:
6857             case GL_UNSIGNED_INT:
6858             case GL_FLOAT:
6859               if (myswapBytes) {
6860                   widget.ub[0] = iter[3];
6861                   widget.ub[1] = iter[2];
6862                   widget.ub[2] = iter[1];
6863                   widget.ub[3] = iter[0];
6864               } else {
6865                   widget.ub[0] = iter[0];
6866                   widget.ub[1] = iter[1];
6867                   widget.ub[2] = iter[2];
6868                   widget.ub[3] = iter[3];
6869               }
6870               if (type == GL_FLOAT) {
6871                   if (indexFormat) {
6872                       *iter2++ = widget.f;
6873                   } else {
6874                       *iter2++ = 65535 * widget.f;
6875                   }
6876               } else if (type == GL_UNSIGNED_INT) {
6877                   if (indexFormat) {
6878                       *iter2++ = widget.ui;
6879                   } else {
6880                       *iter2++ = widget.ui >> 16;
6881                   }
6882               } else {
6883                   if (indexFormat) {
6884                       *iter2++ = widget.i;
6885                   } else {
6886                       *iter2++ = widget.i >> 15;
6887                   }
6888               }
6889               break;
6890             default:
6891               assert(0);
6892             }
6893
6894             iter+= elementSize;
6895          } /* for ww */
6896          rowStart+= rowSize;
6897
6898          iter= rowStart;        /* for assertion purposes */
6899       } /* for hh */
6900
6901       start+= imageSize;
6902    } /* for dd */
6903
6904    /* iterators should be one byte past end */
6905    if (!isTypePackedPixel(type)) {
6906       assert(iter2 == &newImage[width*height*depth*components]);
6907    }
6908    else {
6909       assert(iter2 == &newImage[width*height*depth*
6910                                 elements_per_group(format,0)]);
6911    }
6912    assert( iter == &((const GLubyte *)userImage)[rowSize*height*depth +
6913                                         psm->unpack_skip_rows * rowSize +
6914                                         psm->unpack_skip_pixels * groupSize +
6915                                         /*3dstuff*/
6916                                         psm->unpack_skip_images * imageSize] );
6917 } /* fillImage3D () */
6918
6919 static void scaleInternal3D(GLint components,
6920                             GLint widthIn, GLint heightIn, GLint depthIn,
6921                             const GLushort *dataIn,
6922                             GLint widthOut, GLint heightOut, GLint depthOut,
6923                             GLushort *dataOut)
6924 {
6925     float x, lowx, highx, convx, halfconvx;
6926     float y, lowy, highy, convy, halfconvy;
6927     float z, lowz, highz, convz, halfconvz;
6928     float xpercent,ypercent,zpercent;
6929     float percent;
6930     /* Max components in a format is 4, so... */
6931     float totals[4];
6932     float volume;
6933     int i,j,d,k,zint,yint,xint,xindex,yindex,zindex;
6934     int temp;
6935
6936     convz = (float) depthIn/depthOut;
6937     convy = (float) heightIn/heightOut;
6938     convx = (float) widthIn/widthOut;
6939     halfconvx = convx/2;
6940     halfconvy = convy/2;
6941     halfconvz = convz/2;
6942     for (d = 0; d < depthOut; d++) {
6943        z = convz * (d+0.5);
6944        if (depthIn > depthOut) {
6945            highz = z + halfconvz;
6946            lowz = z - halfconvz;
6947        } else {
6948            highz = z + 0.5;
6949            lowz = z - 0.5;
6950        }
6951        for (i = 0; i < heightOut; i++) {
6952            y = convy * (i+0.5);
6953            if (heightIn > heightOut) {
6954                highy = y + halfconvy;
6955                lowy = y - halfconvy;
6956            } else {
6957                highy = y + 0.5;
6958                lowy = y - 0.5;
6959            }
6960            for (j = 0; j < widthOut; j++) {
6961                x = convx * (j+0.5);
6962                if (widthIn > widthOut) {
6963                    highx = x + halfconvx;
6964                    lowx = x - halfconvx;
6965                } else {
6966                    highx = x + 0.5;
6967                    lowx = x - 0.5;
6968                }
6969
6970                /*
6971                ** Ok, now apply box filter to box that goes from (lowx, lowy,
6972                ** lowz) to (highx, highy, highz) on input data into this pixel
6973                ** on output data.
6974                */
6975                totals[0] = totals[1] = totals[2] = totals[3] = 0.0;
6976                volume = 0.0;
6977
6978                z = lowz;
6979                zint = floor(z);
6980                while (z < highz) {
6981                   zindex = (zint + depthIn) % depthIn;
6982                   if (highz < zint+1) {
6983                       zpercent = highz - z;
6984                   } else {
6985                       zpercent = zint+1 - z;
6986                   }
6987
6988                   y = lowy;
6989                   yint = floor(y);
6990                   while (y < highy) {
6991                       yindex = (yint + heightIn) % heightIn;
6992                       if (highy < yint+1) {
6993                           ypercent = highy - y;
6994                       } else {
6995                           ypercent = yint+1 - y;
6996                       }
6997
6998                       x = lowx;
6999                       xint = floor(x);
7000
7001                       while (x < highx) {
7002                           xindex = (xint + widthIn) % widthIn;
7003                           if (highx < xint+1) {
7004                               xpercent = highx - x;
7005                           } else {
7006                               xpercent = xint+1 - x;
7007                           }
7008
7009                           percent = xpercent * ypercent * zpercent;
7010                           volume += percent;
7011
7012                           temp = (xindex + (yindex*widthIn) +
7013                                   (zindex*widthIn*heightIn)) * components;
7014                           for (k = 0; k < components; k++) {
7015                               assert(0 <= (temp+k) &&
7016                                      (temp+k) <
7017                                      (widthIn*heightIn*depthIn*components));
7018                               totals[k] += dataIn[temp + k] * percent;
7019                           }
7020
7021                           xint++;
7022                           x = xint;
7023                       } /* while x */
7024
7025                       yint++;
7026                       y = yint;
7027                   } /* while y */
7028
7029                   zint++;
7030                   z = zint;
7031                } /* while z */
7032
7033                temp = (j + (i * widthOut) +
7034                        (d*widthOut*heightOut)) * components;
7035                for (k = 0; k < components; k++) {
7036                    /* totals[] should be rounded in the case of enlarging an
7037                     * RGB ramp when the type is 332 or 4444
7038                     */
7039                    assert(0 <= (temp+k) &&
7040                           (temp+k) < (widthOut*heightOut*depthOut*components));
7041                    dataOut[temp + k] = (totals[k]+0.5)/volume;
7042                }
7043            } /* for j */
7044        } /* for i */
7045     } /* for d */
7046 } /* scaleInternal3D() */
7047
7048 static void emptyImage3D(const PixelStorageModes *psm,
7049                          GLint width, GLint height, GLint depth,
7050                          GLenum format, GLenum type, GLboolean indexFormat,
7051                          const GLushort *oldImage, void *userImage)
7052 {
7053    int myswapBytes;
7054    int components;
7055    int groupsPerLine;
7056    int elementSize;
7057    int groupSize;
7058    int rowSize;
7059    int padding;
7060    GLubyte *start, *rowStart, *iter;
7061    int elementsPerLine;
7062    const GLushort *iter2;
7063    int ii, jj, dd, k;
7064    int rowsPerImage;
7065    int imageSize;
7066
7067    myswapBytes= psm->pack_swap_bytes;
7068    components = elements_per_group(format,type);
7069    if (psm->pack_row_length > 0) {
7070       groupsPerLine = psm->pack_row_length;
7071    }
7072    else {
7073       groupsPerLine = width;
7074    }
7075
7076    elementSize= bytes_per_element(type);
7077    groupSize= elementSize * components;
7078    if (elementSize == 1) myswapBytes= 0;
7079
7080    /* 3dstuff begin */
7081    if (psm->pack_image_height > 0) {
7082       rowsPerImage= psm->pack_image_height;
7083    }
7084    else {
7085       rowsPerImage= height;
7086    }
7087
7088    /* 3dstuff end */
7089
7090    rowSize = groupsPerLine * groupSize;
7091    padding = rowSize % psm->pack_alignment;
7092    if (padding) {
7093       rowSize+= psm->pack_alignment - padding;
7094    }
7095
7096    imageSize= rowsPerImage * rowSize; /* 3dstuff */
7097
7098    start = (GLubyte *)userImage + psm->pack_skip_rows * rowSize +
7099                                   psm->pack_skip_pixels * groupSize +
7100                                   /*3dstuff*/
7101                                   psm->pack_skip_images * imageSize;
7102    elementsPerLine= width * components;
7103
7104    iter2 = oldImage;
7105    for (dd= 0; dd < depth; dd++) {
7106       rowStart= start;
7107
7108       for (ii= 0; ii< height; ii++) {
7109          iter = rowStart;
7110
7111          for (jj = 0; jj < elementsPerLine; jj++) {
7112             Type_Widget widget;
7113             float shoveComponents[4];
7114
7115             switch(type){
7116             case GL_UNSIGNED_BYTE:
7117               if (indexFormat) {
7118                   *iter = *iter2++;
7119               } else {
7120                   *iter = *iter2++ >> 8;
7121               }
7122               break;
7123             case GL_BYTE:
7124               if (indexFormat) {
7125                   *((GLbyte *) iter) = *iter2++;
7126               } else {
7127                   *((GLbyte *) iter) = *iter2++ >> 9;
7128               }
7129               break;
7130             case GL_UNSIGNED_BYTE_3_3_2:
7131               for (k = 0; k < 3; k++) {
7132                  shoveComponents[k]= *iter2++ / 65535.0;
7133               }
7134               shove332(shoveComponents,0,(void *)iter);
7135               break;
7136             case GL_UNSIGNED_BYTE_2_3_3_REV:
7137               for (k = 0; k < 3; k++) {
7138                  shoveComponents[k]= *iter2++ / 65535.0;
7139               }
7140               shove233rev(shoveComponents,0,(void *)iter);
7141               break;
7142             case GL_UNSIGNED_SHORT_5_6_5:               
7143               for (k = 0; k < 3; k++) {
7144                  shoveComponents[k]= *iter2++ / 65535.0;
7145               }
7146               shove565(shoveComponents,0,(void *)&widget.us[0]);
7147               if (myswapBytes) {
7148                  iter[0] = widget.ub[1];
7149                  iter[1] = widget.ub[0];
7150               }
7151               else {
7152                  *(GLushort *)iter = widget.us[0];
7153               }
7154               break;
7155             case GL_UNSIGNED_SHORT_5_6_5_REV:           
7156               for (k = 0; k < 3; k++) {
7157                  shoveComponents[k]= *iter2++ / 65535.0;
7158               }
7159               shove565rev(shoveComponents,0,(void *)&widget.us[0]);
7160               if (myswapBytes) {
7161                  iter[0] = widget.ub[1];
7162                  iter[1] = widget.ub[0];
7163               }
7164               else {
7165                  *(GLushort *)iter = widget.us[0];
7166               }
7167               break;
7168             case GL_UNSIGNED_SHORT_4_4_4_4:
7169               for (k = 0; k < 4; k++) {
7170                  shoveComponents[k]= *iter2++ / 65535.0;
7171               }
7172               shove4444(shoveComponents,0,(void *)&widget.us[0]);
7173               if (myswapBytes) {
7174                  iter[0] = widget.ub[1];
7175                  iter[1] = widget.ub[0];
7176               } else {
7177                  *(GLushort *)iter = widget.us[0];
7178               }
7179               break;
7180             case GL_UNSIGNED_SHORT_4_4_4_4_REV:
7181               for (k = 0; k < 4; k++) {
7182                  shoveComponents[k]= *iter2++ / 65535.0;
7183               }
7184               shove4444rev(shoveComponents,0,(void *)&widget.us[0]);
7185               if (myswapBytes) {
7186                  iter[0] = widget.ub[1];
7187                  iter[1] = widget.ub[0];
7188               } else {
7189                  *(GLushort *)iter = widget.us[0];
7190               }
7191               break;
7192             case GL_UNSIGNED_SHORT_5_5_5_1:
7193               for (k = 0; k < 4; k++) {
7194                  shoveComponents[k]= *iter2++ / 65535.0;
7195               }
7196               shove5551(shoveComponents,0,(void *)&widget.us[0]);
7197               if (myswapBytes) {
7198                  iter[0] = widget.ub[1];
7199                  iter[1] = widget.ub[0];
7200               } else {
7201                  *(GLushort *)iter = widget.us[0];
7202               }
7203               break;
7204             case GL_UNSIGNED_SHORT_1_5_5_5_REV:
7205               for (k = 0; k < 4; k++) {
7206                  shoveComponents[k]= *iter2++ / 65535.0;
7207               }
7208               shove1555rev(shoveComponents,0,(void *)&widget.us[0]);
7209               if (myswapBytes) {
7210                  iter[0] = widget.ub[1];
7211                  iter[1] = widget.ub[0];
7212               } else {
7213                  *(GLushort *)iter = widget.us[0];
7214               }
7215               break;
7216             case GL_UNSIGNED_SHORT:
7217             case GL_SHORT:
7218               if (type == GL_SHORT) {
7219                   if (indexFormat) {
7220                       widget.s[0] = *iter2++;
7221                   } else {
7222                       widget.s[0] = *iter2++ >> 1;
7223                   }
7224               } else {
7225                   widget.us[0] = *iter2++;
7226               }
7227               if (myswapBytes) {
7228                   iter[0] = widget.ub[1];
7229                   iter[1] = widget.ub[0];
7230               } else {
7231                   iter[0] = widget.ub[0];
7232                   iter[1] = widget.ub[1];
7233               }
7234               break;
7235             case GL_UNSIGNED_INT_8_8_8_8:
7236                for (k = 0; k < 4; k++) {
7237                   shoveComponents[k]= *iter2++ / 65535.0;
7238                }
7239                shove8888(shoveComponents,0,(void *)&widget.ui);
7240                if (myswapBytes) {
7241                    iter[3] = widget.ub[0];
7242                    iter[2] = widget.ub[1];
7243                    iter[1] = widget.ub[2];
7244                    iter[0] = widget.ub[3];
7245                } else {
7246                    *(GLuint *)iter= widget.ui;
7247                }
7248                break;
7249             case GL_UNSIGNED_INT_8_8_8_8_REV:
7250                for (k = 0; k < 4; k++) {
7251                   shoveComponents[k]= *iter2++ / 65535.0;
7252                }
7253                shove8888rev(shoveComponents,0,(void *)&widget.ui);
7254                if (myswapBytes) {
7255                    iter[3] = widget.ub[0];
7256                    iter[2] = widget.ub[1];
7257                    iter[1] = widget.ub[2];
7258                    iter[0] = widget.ub[3];
7259                } else {
7260                    *(GLuint *)iter= widget.ui;
7261                }
7262                break;
7263             case GL_UNSIGNED_INT_10_10_10_2:
7264                for (k = 0; k < 4; k++) {
7265                   shoveComponents[k]= *iter2++ / 65535.0;
7266                }
7267                shove1010102(shoveComponents,0,(void *)&widget.ui);
7268                if (myswapBytes) {
7269                    iter[3] = widget.ub[0];
7270                    iter[2] = widget.ub[1];
7271                    iter[1] = widget.ub[2];
7272                    iter[0] = widget.ub[3];
7273                } else {
7274                    *(GLuint *)iter= widget.ui;
7275                }
7276                break;
7277             case GL_UNSIGNED_INT_2_10_10_10_REV:
7278                for (k = 0; k < 4; k++) {
7279                   shoveComponents[k]= *iter2++ / 65535.0;
7280                }
7281                shove2101010rev(shoveComponents,0,(void *)&widget.ui);
7282                if (myswapBytes) {
7283                    iter[3] = widget.ub[0];
7284                    iter[2] = widget.ub[1];
7285                    iter[1] = widget.ub[2];
7286                    iter[0] = widget.ub[3];
7287                } else {
7288                    *(GLuint *)iter= widget.ui;
7289                }
7290                break;
7291             case GL_INT:
7292             case GL_UNSIGNED_INT:
7293             case GL_FLOAT:
7294               if (type == GL_FLOAT) {
7295                   if (indexFormat) {
7296                       widget.f = *iter2++;
7297                   } else {
7298                       widget.f = *iter2++ / (float) 65535.0;
7299                   }
7300               } else if (type == GL_UNSIGNED_INT) {
7301                   if (indexFormat) {
7302                       widget.ui = *iter2++;
7303                   } else {
7304                       widget.ui = (unsigned int) *iter2++ * 65537;
7305                   }
7306               } else {
7307                   if (indexFormat) {
7308                       widget.i = *iter2++;
7309                   } else {
7310                       widget.i = ((unsigned int) *iter2++ * 65537)/2;
7311                   }
7312               }
7313               if (myswapBytes) {
7314                   iter[3] = widget.ub[0];
7315                   iter[2] = widget.ub[1];
7316                   iter[1] = widget.ub[2];
7317                   iter[0] = widget.ub[3];
7318               } else {
7319                   iter[0] = widget.ub[0];
7320                   iter[1] = widget.ub[1];
7321                   iter[2] = widget.ub[2];
7322                   iter[3] = widget.ub[3];
7323               }
7324               break;
7325             default:
7326                assert(0);
7327             }
7328
7329             iter+= elementSize;
7330          }  /* for jj */
7331
7332          rowStart+= rowSize;
7333       } /* for ii */
7334
7335       start+= imageSize;
7336    } /* for dd */
7337
7338    /* iterators should be one byte past end */
7339    if (!isTypePackedPixel(type)) {
7340       assert(iter2 == &oldImage[width*height*depth*components]);
7341    }
7342    else {
7343       assert(iter2 == &oldImage[width*height*depth*
7344                                 elements_per_group(format,0)]);
7345    }
7346    assert( iter == &((GLubyte *)userImage)[rowSize*height*depth +
7347                                         psm->unpack_skip_rows * rowSize +
7348                                         psm->unpack_skip_pixels * groupSize +
7349                                         /*3dstuff*/
7350                                         psm->unpack_skip_images * imageSize] );
7351 } /* emptyImage3D() */
7352
7353 static
7354 int gluScaleImage3D(GLenum format,
7355                     GLint widthIn, GLint heightIn, GLint depthIn,
7356                     GLenum typeIn, const void *dataIn,
7357                     GLint widthOut, GLint heightOut, GLint depthOut,
7358                     GLenum typeOut, void *dataOut)
7359 {
7360    int components;
7361    GLushort *beforeImage, *afterImage;
7362    PixelStorageModes psm;
7363
7364    if (widthIn == 0 || heightIn == 0 || depthIn == 0 ||
7365        widthOut == 0 || heightOut == 0 || depthOut == 0) {
7366       return 0;
7367    }
7368
7369    if (widthIn < 0 || heightIn < 0 || depthIn < 0 ||
7370        widthOut < 0 || heightOut < 0 || depthOut < 0) {
7371       return GLU_INVALID_VALUE;
7372    }
7373
7374    if (!legalFormat(format) || !legalType(typeIn) || !legalType(typeOut) ||
7375        typeIn == GL_BITMAP || typeOut == GL_BITMAP) {
7376       return GLU_INVALID_ENUM;
7377    }
7378    if (!isLegalFormatForPackedPixelType(format, typeIn)) {
7379       return GLU_INVALID_OPERATION;
7380    }
7381    if (!isLegalFormatForPackedPixelType(format, typeOut)) {
7382       return GLU_INVALID_OPERATION;
7383    }
7384
7385    beforeImage = malloc(imageSize3D(widthIn, heightIn, depthIn, format,
7386                                     GL_UNSIGNED_SHORT));
7387    afterImage = malloc(imageSize3D(widthOut, heightOut, depthOut, format,
7388                                    GL_UNSIGNED_SHORT));
7389    if (beforeImage == NULL || afterImage == NULL) {
7390        free(beforeImage);
7391        free(afterImage);
7392        return GLU_OUT_OF_MEMORY;
7393    }
7394    retrieveStoreModes3D(&psm);
7395
7396    fillImage3D(&psm,widthIn,heightIn,depthIn,format,typeIn, is_index(format),
7397                dataIn, beforeImage);
7398    components = elements_per_group(format,0);
7399    scaleInternal3D(components,widthIn,heightIn,depthIn,beforeImage,
7400                    widthOut,heightOut,depthOut,afterImage);
7401    emptyImage3D(&psm,widthOut,heightOut,depthOut,format,typeOut,
7402                 is_index(format),afterImage, dataOut);
7403    free((void *) beforeImage);
7404    free((void *) afterImage);
7405
7406    return 0;
7407 } /* gluScaleImage3D() */
7408
7409
7410 static void closestFit3D(GLenum target, GLint width, GLint height, GLint depth,
7411                          GLint internalFormat, GLenum format, GLenum type,
7412                          GLint *newWidth, GLint *newHeight, GLint *newDepth)
7413 {
7414    GLint widthPowerOf2= nearestPower(width);
7415    GLint heightPowerOf2= nearestPower(height);          
7416    GLint depthPowerOf2= nearestPower(depth);
7417    GLint proxyWidth;
7418
7419    do {
7420       /* compute level 1 width & height & depth, clamping each at 1 */
7421       GLint widthAtLevelOne= (widthPowerOf2 > 1) ?
7422                               widthPowerOf2 >> 1 :
7423                               widthPowerOf2;
7424       GLint heightAtLevelOne= (heightPowerOf2 > 1) ?
7425                                heightPowerOf2 >> 1 :
7426                                heightPowerOf2;
7427       GLint depthAtLevelOne= (depthPowerOf2 > 1) ?
7428                               depthPowerOf2 >> 1 :
7429                               depthPowerOf2;
7430       GLenum proxyTarget = GL_PROXY_TEXTURE_3D;
7431       assert(widthAtLevelOne > 0);
7432       assert(heightAtLevelOne > 0);
7433       assert(depthAtLevelOne > 0);
7434
7435       /* does width x height x depth at level 1 & all their mipmaps fit? */
7436       assert(target == GL_TEXTURE_3D || target == GL_PROXY_TEXTURE_3D);
7437       gluTexImage3D(proxyTarget, 1, /* must be non-zero */
7438                     internalFormat,
7439                     widthAtLevelOne,heightAtLevelOne,depthAtLevelOne,
7440                     0,format,type,NULL);
7441       glGetTexLevelParameteriv(proxyTarget, 1,GL_TEXTURE_WIDTH,&proxyWidth);
7442       /* does it fit??? */
7443       if (proxyWidth == 0) { /* nope, so try again with these sizes */
7444          if (widthPowerOf2 == 1 && heightPowerOf2 == 1 &&
7445              depthPowerOf2 == 1) {
7446             *newWidth= *newHeight= *newDepth= 1; /* must fit 1x1x1 texture */
7447             return;
7448          }
7449          widthPowerOf2= widthAtLevelOne;
7450          heightPowerOf2= heightAtLevelOne;
7451          depthPowerOf2= depthAtLevelOne;
7452       }
7453       /* else it does fit */
7454    } while (proxyWidth == 0);
7455    /* loop must terminate! */
7456
7457    /* return the width & height at level 0 that fits */
7458    *newWidth= widthPowerOf2;
7459    *newHeight= heightPowerOf2;
7460    *newDepth= depthPowerOf2;
7461 /*printf("Proxy Textures\n");*/
7462 } /* closestFit3D() */
7463
7464 static void halveImagePackedPixelSlice(int components,
7465                                        void (*extractPackedPixel)
7466                                        (int, const void *,GLfloat []),
7467                                        void (*shovePackedPixel)
7468                                        (const GLfloat [],int, void *),
7469                                        GLint width, GLint height, GLint depth,
7470                                        const void *dataIn, void *dataOut,
7471                                        GLint pixelSizeInBytes,
7472                                        GLint rowSizeInBytes,
7473                                        GLint imageSizeInBytes,
7474                                        GLint isSwap)
7475 {
7476    int ii, jj;
7477    int halfWidth= width / 2;
7478    int halfHeight= height / 2;
7479    int halfDepth= depth / 2;
7480    const char *src= (const char *)dataIn;
7481    int outIndex= 0;
7482
7483    assert((width == 1 || height == 1) && depth >= 2);
7484
7485    if (width == height) {       /* a 1-pixel column viewed from top */
7486       assert(width == 1 && height == 1);
7487       assert(depth >= 2);
7488
7489       for (ii= 0; ii< halfDepth; ii++) {
7490          float totals[4];
7491          float extractTotals[BOX2][4];
7492          int cc;
7493
7494          (*extractPackedPixel)(isSwap,src,&extractTotals[0][0]);
7495          (*extractPackedPixel)(isSwap,(src+imageSizeInBytes),
7496                                &extractTotals[1][0]);
7497          for (cc = 0; cc < components; cc++) {
7498             int kk;
7499
7500             /* average 2 pixels since only a column */
7501             totals[cc]= 0.0;
7502             /* totals[RED]= extractTotals[0][RED]+extractTotals[1][RED];
7503              * totals[RED]/= 2.0;
7504              */
7505             for (kk = 0; kk < BOX2; kk++) {
7506               totals[cc]+= extractTotals[kk][cc];
7507             }
7508             totals[cc]/= (float)BOX2;
7509          } /* for cc */
7510         
7511          (*shovePackedPixel)(totals,outIndex,dataOut);
7512          outIndex++;
7513          /* skip over to next group of 2 */
7514          src+= imageSizeInBytes + imageSizeInBytes;
7515       } /* for ii */
7516    }
7517    else if (height == 1) {      /* horizontal slice viewed from top */
7518       assert(width != 1);
7519
7520       for (ii= 0; ii< halfDepth; ii++) {
7521          for (jj= 0; jj< halfWidth; jj++) {
7522              float totals[4];
7523              float extractTotals[BOX4][4];
7524              int cc;
7525
7526              (*extractPackedPixel)(isSwap,src,
7527                                    &extractTotals[0][0]);
7528              (*extractPackedPixel)(isSwap,(src+pixelSizeInBytes),
7529                                    &extractTotals[1][0]);
7530              (*extractPackedPixel)(isSwap,(src+imageSizeInBytes),
7531                                    &extractTotals[2][0]);
7532              (*extractPackedPixel)(isSwap,
7533                                    (src+imageSizeInBytes+pixelSizeInBytes),
7534                                    &extractTotals[3][0]);
7535              for (cc = 0; cc < components; cc++) {
7536                 int kk;
7537
7538                 /* grab 4 pixels to average */
7539                 totals[cc]= 0.0;
7540                 /* totals[RED]= extractTotals[0][RED]+extractTotals[1][RED]+
7541                  *              extractTotals[2][RED]+extractTotals[3][RED];
7542                  * totals[RED]/= 4.0;
7543                  */
7544                 for (kk = 0; kk < BOX4; kk++) {
7545                    totals[cc]+= extractTotals[kk][cc];
7546                 }
7547                 totals[cc]/= (float)BOX4;
7548              }
7549              (*shovePackedPixel)(totals,outIndex,dataOut);
7550
7551              outIndex++;
7552              /* skip over to next horizontal square of 4 */
7553              src+= imageSizeInBytes + imageSizeInBytes;
7554          }
7555       }
7556
7557       /* assert() */
7558    }
7559    else if (width == 1) {       /* vertical slice viewed from top */
7560       assert(height != 1);
7561
7562       for (ii= 0; ii< halfDepth; ii++) {
7563          for (jj= 0; jj< halfHeight; jj++) {
7564             float totals[4];
7565             float extractTotals[BOX4][4];
7566             int cc;
7567
7568             (*extractPackedPixel)(isSwap,src,
7569                                   &extractTotals[0][0]);
7570             (*extractPackedPixel)(isSwap,(src+rowSizeInBytes),
7571                                   &extractTotals[1][0]);
7572             (*extractPackedPixel)(isSwap,(src+imageSizeInBytes),
7573                                   &extractTotals[2][0]);
7574             (*extractPackedPixel)(isSwap,
7575                                   (src+imageSizeInBytes+rowSizeInBytes),
7576                                   &extractTotals[3][0]);
7577             for (cc = 0; cc < components; cc++) {
7578                int kk;
7579
7580                /* grab 4 pixels to average */
7581                totals[cc]= 0.0;
7582                /* totals[RED]= extractTotals[0][RED]+extractTotals[1][RED]+
7583                 *              extractTotals[2][RED]+extractTotals[3][RED];
7584                 * totals[RED]/= 4.0;
7585                 */
7586                for (kk = 0; kk < BOX4; kk++) {
7587                   totals[cc]+= extractTotals[kk][cc];
7588                }
7589                totals[cc]/= (float)BOX4;
7590             }
7591             (*shovePackedPixel)(totals,outIndex,dataOut);
7592
7593             outIndex++;
7594
7595             /* skip over to next vertical square of 4 */
7596             src+= imageSizeInBytes + imageSizeInBytes;
7597          }
7598       }
7599       /* assert() */
7600    }
7601
7602 } /* halveImagePackedPixelSlice() */
7603
7604 static void halveImagePackedPixel3D(int components,
7605                                     void (*extractPackedPixel)
7606                                     (int, const void *,GLfloat []),
7607                                     void (*shovePackedPixel)
7608                                     (const GLfloat [],int, void *),
7609                                     GLint width, GLint height, GLint depth,
7610                                     const void *dataIn, void *dataOut,
7611                                     GLint pixelSizeInBytes,
7612                                     GLint rowSizeInBytes,
7613                                     GLint imageSizeInBytes,
7614                                     GLint isSwap)
7615 {
7616    if (depth == 1) {
7617       assert(1 <= width && 1 <= height);
7618
7619       halveImagePackedPixel(components,extractPackedPixel,shovePackedPixel,
7620                             width,height,dataIn,dataOut,pixelSizeInBytes,
7621                             rowSizeInBytes,isSwap);
7622       return;
7623    }
7624    /* a horizontal or vertical slice viewed from top */
7625    else if (width == 1 || height == 1) {
7626       assert(1 <= depth);
7627
7628       halveImagePackedPixelSlice(components,
7629                                  extractPackedPixel,shovePackedPixel,
7630                                  width, height, depth, dataIn, dataOut,
7631                                  pixelSizeInBytes, rowSizeInBytes,
7632                                  imageSizeInBytes, isSwap);
7633       return;
7634    }
7635    {
7636       int ii, jj, dd;
7637
7638       int halfWidth= width / 2;
7639       int halfHeight= height / 2;
7640       int halfDepth= depth / 2;
7641       const char *src= (const char *) dataIn;
7642       int padBytes= rowSizeInBytes - (width*pixelSizeInBytes);
7643       int outIndex= 0;
7644
7645       for (dd= 0; dd < halfDepth; dd++) {
7646          for (ii= 0; ii< halfHeight; ii++) {
7647             for (jj= 0; jj< halfWidth; jj++) {
7648 #define BOX8 8
7649                float totals[4]; /* 4 is maximum components */
7650                float extractTotals[BOX8][4]; /* 4 is maximum components */
7651                int cc;
7652
7653                (*extractPackedPixel)(isSwap,src,
7654                                      &extractTotals[0][0]);
7655                (*extractPackedPixel)(isSwap,(src+pixelSizeInBytes),
7656                                      &extractTotals[1][0]);
7657                (*extractPackedPixel)(isSwap,(src+rowSizeInBytes),
7658                                      &extractTotals[2][0]);
7659                (*extractPackedPixel)(isSwap,
7660                                      (src+rowSizeInBytes+pixelSizeInBytes),
7661                                      &extractTotals[3][0]);
7662
7663                (*extractPackedPixel)(isSwap,(src+imageSizeInBytes),
7664                                      &extractTotals[4][0]);
7665                (*extractPackedPixel)(isSwap,(src+pixelSizeInBytes+imageSizeInBytes),
7666                                      &extractTotals[5][0]);
7667                (*extractPackedPixel)(isSwap,(src+rowSizeInBytes+imageSizeInBytes),
7668                                      &extractTotals[6][0]);
7669                (*extractPackedPixel)(isSwap,
7670                                      (src+rowSizeInBytes+pixelSizeInBytes+imageSizeInBytes),
7671                                      &extractTotals[7][0]);
7672                for (cc = 0; cc < components; cc++) {
7673                   int kk;
7674
7675                   /* grab 8 pixels to average */
7676                   totals[cc]= 0.0;
7677                   /* totals[RED]= extractTotals[0][RED]+extractTotals[1][RED]+
7678                    *              extractTotals[2][RED]+extractTotals[3][RED]+
7679                    *              extractTotals[4][RED]+extractTotals[5][RED]+
7680                    *              extractTotals[6][RED]+extractTotals[7][RED];
7681                    * totals[RED]/= 8.0;
7682                    */
7683                   for (kk = 0; kk < BOX8; kk++) {
7684                      totals[cc]+= extractTotals[kk][cc];
7685                   }
7686                   totals[cc]/= (float)BOX8;
7687                }
7688                (*shovePackedPixel)(totals,outIndex,dataOut);
7689
7690                outIndex++;
7691                /* skip over to next square of 4 */
7692                src+= pixelSizeInBytes + pixelSizeInBytes;
7693             }
7694             /* skip past pad bytes, if any, to get to next row */
7695             src+= padBytes;
7696
7697             /* src is at beginning of a row here, but it's the second row of
7698              * the square block of 4 pixels that we just worked on so we
7699              * need to go one more row.
7700              * i.e.,
7701              *                   OO...
7702              *           here -->OO...
7703              *       but want -->OO...
7704              *                   OO...
7705              *                   ...
7706              */
7707             src+= rowSizeInBytes;
7708          }
7709
7710          src+= imageSizeInBytes;
7711       } /* for dd */
7712
7713       /* both pointers must reach one byte after the end */
7714       assert(src == &((const char *)dataIn)[rowSizeInBytes*height*depth]);
7715       assert(outIndex == halfWidth * halfHeight * halfDepth);
7716    } /* for dd */
7717
7718 } /* halveImagePackedPixel3D() */
7719
7720 static int gluBuild3DMipmapLevelsCore(GLenum target, GLint internalFormat,
7721                                       GLsizei width,
7722                                       GLsizei height,
7723                                       GLsizei depth,
7724                                       GLsizei widthPowerOf2,
7725                                       GLsizei heightPowerOf2,
7726                                       GLsizei depthPowerOf2,
7727                                       GLenum format, GLenum type,
7728                                       GLint userLevel,
7729                                       GLint baseLevel,GLint maxLevel,
7730                                       const void *data)
7731 {
7732    GLint newWidth, newHeight, newDepth;
7733    GLint level, levels;
7734    const void *usersImage;
7735    void *srcImage, *dstImage;
7736    __GLU_INIT_SWAP_IMAGE;
7737    GLint memReq;
7738    GLint cmpts;
7739
7740    GLint myswapBytes, groupsPerLine, elementSize, groupSize;
7741    GLint rowsPerImage, imageSize;
7742    GLint rowSize, padding;
7743    PixelStorageModes psm;
7744
7745    assert(checkMipmapArgs(internalFormat,format,type) == 0);
7746    assert(width >= 1 && height >= 1 && depth >= 1);
7747    assert(type != GL_BITMAP);
7748
7749    srcImage = dstImage = NULL;
7750
7751    newWidth= widthPowerOf2;
7752    newHeight= heightPowerOf2;
7753    newDepth= depthPowerOf2;
7754    levels = computeLog(newWidth);
7755    level = computeLog(newHeight);
7756    if (level > levels) levels=level;
7757    level = computeLog(newDepth);
7758    if (level > levels) levels=level;
7759
7760    levels+= userLevel;
7761
7762    retrieveStoreModes3D(&psm);
7763    myswapBytes = psm.unpack_swap_bytes;
7764    cmpts = elements_per_group(format,type);
7765    if (psm.unpack_row_length > 0) {
7766        groupsPerLine = psm.unpack_row_length;
7767    } else {
7768        groupsPerLine = width;
7769    }
7770
7771    elementSize = bytes_per_element(type);
7772    groupSize = elementSize * cmpts;
7773    if (elementSize == 1) myswapBytes = 0;
7774
7775    /* 3dstuff begin */
7776    if (psm.unpack_image_height > 0) {
7777       rowsPerImage= psm.unpack_image_height;
7778    }
7779    else {
7780       rowsPerImage= height;
7781    }
7782
7783    /* 3dstuff end */
7784    rowSize = groupsPerLine * groupSize;
7785    padding = (rowSize % psm.unpack_alignment);
7786    if (padding) {
7787        rowSize += psm.unpack_alignment - padding;
7788    }
7789
7790    imageSize= rowsPerImage * rowSize; /* 3dstuff */
7791
7792    usersImage = (const GLubyte *)data + psm.unpack_skip_rows * rowSize +
7793                                   psm.unpack_skip_pixels * groupSize +
7794                                   /* 3dstuff */
7795                                   psm.unpack_skip_images * imageSize;
7796
7797    glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
7798    glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
7799    glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
7800    glPixelStorei(GL_UNPACK_SKIP_IMAGES, 0);
7801    glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, 0);
7802
7803    level = userLevel;
7804
7805    if (width == newWidth && height == newHeight && depth == newDepth) {
7806        /* Use usersImage for level userLevel */
7807        if (baseLevel <= level && level <= maxLevel) {
7808           gluTexImage3D(target, level, internalFormat, width,
7809                        height, depth, 0, format, type,
7810                        usersImage);
7811        }
7812        if(levels == 0) { /* we're done. clean up and return */
7813          glPixelStorei(GL_UNPACK_ALIGNMENT, psm.unpack_alignment);
7814          glPixelStorei(GL_UNPACK_SKIP_ROWS, psm.unpack_skip_rows);
7815          glPixelStorei(GL_UNPACK_SKIP_PIXELS, psm.unpack_skip_pixels);
7816          glPixelStorei(GL_UNPACK_ROW_LENGTH, psm.unpack_row_length);
7817          glPixelStorei(GL_UNPACK_SWAP_BYTES, psm.unpack_swap_bytes);
7818          glPixelStorei(GL_UNPACK_SKIP_IMAGES, psm.unpack_skip_images);
7819          glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, psm.unpack_image_height);
7820          return 0;
7821        }
7822        {
7823           int nextWidth= newWidth/2;
7824           int nextHeight= newHeight/2;
7825           int nextDepth= newDepth/2;
7826
7827           /* clamp to 1 */
7828           if (nextWidth < 1) nextWidth= 1;
7829           if (nextHeight < 1) nextHeight= 1;
7830           if (nextDepth < 1) nextDepth= 1;      
7831        memReq = imageSize3D(nextWidth, nextHeight, nextDepth, format, type);
7832        }
7833        switch(type) {
7834        case GL_UNSIGNED_BYTE:
7835          dstImage = (GLubyte *)malloc(memReq);
7836          break;
7837        case GL_BYTE:
7838          dstImage = (GLbyte *)malloc(memReq);
7839          break;
7840        case GL_UNSIGNED_SHORT:
7841          dstImage = (GLushort *)malloc(memReq);
7842          break;
7843        case GL_SHORT:
7844          dstImage = (GLshort *)malloc(memReq);
7845          break;
7846        case GL_UNSIGNED_INT:
7847          dstImage = (GLuint *)malloc(memReq);
7848          break;
7849        case GL_INT:
7850          dstImage = (GLint *)malloc(memReq);
7851          break;
7852        case GL_FLOAT:
7853          dstImage = (GLfloat *)malloc(memReq);
7854          break;
7855        case GL_UNSIGNED_BYTE_3_3_2:
7856        case GL_UNSIGNED_BYTE_2_3_3_REV:
7857          dstImage = (GLubyte *)malloc(memReq);
7858          break;
7859        case GL_UNSIGNED_SHORT_5_6_5:
7860        case GL_UNSIGNED_SHORT_5_6_5_REV:
7861        case GL_UNSIGNED_SHORT_4_4_4_4:
7862        case GL_UNSIGNED_SHORT_4_4_4_4_REV:
7863        case GL_UNSIGNED_SHORT_5_5_5_1:
7864        case GL_UNSIGNED_SHORT_1_5_5_5_REV:
7865          dstImage = (GLushort *)malloc(memReq);
7866          break;
7867        case GL_UNSIGNED_INT_8_8_8_8:
7868        case GL_UNSIGNED_INT_8_8_8_8_REV:
7869        case GL_UNSIGNED_INT_10_10_10_2:
7870        case GL_UNSIGNED_INT_2_10_10_10_REV:
7871          dstImage = (GLuint *)malloc(memReq);   
7872          break;
7873        default:
7874          return GLU_INVALID_ENUM; /* assertion */
7875        }
7876        if (dstImage == NULL) {
7877          glPixelStorei(GL_UNPACK_ALIGNMENT, psm.unpack_alignment);
7878          glPixelStorei(GL_UNPACK_SKIP_ROWS, psm.unpack_skip_rows);
7879          glPixelStorei(GL_UNPACK_SKIP_PIXELS, psm.unpack_skip_pixels);
7880          glPixelStorei(GL_UNPACK_ROW_LENGTH, psm.unpack_row_length);
7881          glPixelStorei(GL_UNPACK_SWAP_BYTES, psm.unpack_swap_bytes);
7882          glPixelStorei(GL_UNPACK_SKIP_IMAGES, psm.unpack_skip_images);
7883          glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, psm.unpack_image_height);
7884          return GLU_OUT_OF_MEMORY;
7885        }
7886        else
7887          switch(type) {
7888          case GL_UNSIGNED_BYTE:
7889            if (depth > 1) {
7890              halveImage3D(cmpts,extractUbyte,shoveUbyte,
7891                           width,height,depth,
7892                           usersImage,dstImage,elementSize,groupSize,rowSize,
7893                           imageSize,myswapBytes);
7894            }
7895            else {
7896              halveImage_ubyte(cmpts,width,height,usersImage,dstImage,
7897                               elementSize,rowSize,groupSize);
7898            }
7899            break;
7900          case GL_BYTE:
7901            if (depth > 1) {
7902            halveImage3D(cmpts,extractSbyte,shoveSbyte,
7903                         width,height,depth,
7904                         usersImage,dstImage,elementSize,groupSize,rowSize,
7905                         imageSize,myswapBytes);
7906            }
7907            else {
7908              halveImage_byte(cmpts,width,height,usersImage,dstImage,
7909                              elementSize,rowSize,groupSize);
7910            }
7911            break;
7912          case GL_UNSIGNED_SHORT:
7913            if (depth > 1) {
7914            halveImage3D(cmpts,extractUshort,shoveUshort,
7915                         width,height,depth,
7916                         usersImage,dstImage,elementSize,groupSize,rowSize,
7917                         imageSize,myswapBytes);
7918            }
7919            else {
7920              halveImage_ushort(cmpts,width,height,usersImage,dstImage,
7921                                elementSize,rowSize,groupSize,myswapBytes);
7922            }
7923            break;
7924          case GL_SHORT:
7925            if (depth > 1) {
7926            halveImage3D(cmpts,extractSshort,shoveSshort,
7927                         width,height,depth,
7928                         usersImage,dstImage,elementSize,groupSize,rowSize,
7929                         imageSize,myswapBytes);
7930            }
7931            else {
7932              halveImage_short(cmpts,width,height,usersImage,dstImage,
7933                               elementSize,rowSize,groupSize,myswapBytes);
7934            }
7935            break;
7936          case GL_UNSIGNED_INT:
7937            if (depth > 1) {
7938            halveImage3D(cmpts,extractUint,shoveUint,
7939                         width,height,depth,
7940                         usersImage,dstImage,elementSize,groupSize,rowSize,
7941                         imageSize,myswapBytes);
7942            }
7943            else {
7944              halveImage_uint(cmpts,width,height,usersImage,dstImage,
7945                              elementSize,rowSize,groupSize,myswapBytes);
7946            }
7947            break;
7948          case GL_INT:
7949            if (depth > 1) {
7950            halveImage3D(cmpts,extractSint,shoveSint,
7951                         width,height,depth,
7952                         usersImage,dstImage,elementSize,groupSize,rowSize,
7953                         imageSize,myswapBytes);
7954            }
7955            else {
7956              halveImage_int(cmpts,width,height,usersImage,dstImage,
7957                             elementSize,rowSize,groupSize,myswapBytes);
7958            }
7959            break;
7960          case GL_FLOAT:
7961            if (depth > 1 ) {
7962            halveImage3D(cmpts,extractFloat,shoveFloat,
7963                         width,height,depth,
7964                         usersImage,dstImage,elementSize,groupSize,rowSize,
7965                         imageSize,myswapBytes);
7966            }
7967            else {
7968              halveImage_float(cmpts,width,height,usersImage,dstImage,
7969                               elementSize,rowSize,groupSize,myswapBytes);
7970            }
7971            break;
7972          case GL_UNSIGNED_BYTE_3_3_2:
7973            assert(format == GL_RGB);
7974            halveImagePackedPixel3D(3,extract332,shove332,
7975                                    width,height,depth,usersImage,dstImage,
7976                                    elementSize,rowSize,imageSize,myswapBytes);
7977            break;
7978          case GL_UNSIGNED_BYTE_2_3_3_REV:
7979            assert(format == GL_RGB);
7980            halveImagePackedPixel3D(3,extract233rev,shove233rev,
7981                                    width,height,depth,usersImage,dstImage,
7982                                    elementSize,rowSize,imageSize,myswapBytes);
7983            break;
7984          case GL_UNSIGNED_SHORT_5_6_5:
7985            halveImagePackedPixel3D(3,extract565,shove565,
7986                                    width,height,depth,usersImage,dstImage,
7987                                    elementSize,rowSize,imageSize,myswapBytes);
7988            break;
7989          case GL_UNSIGNED_SHORT_5_6_5_REV:
7990            halveImagePackedPixel3D(3,extract565rev,shove565rev,
7991                                    width,height,depth,usersImage,dstImage,
7992                                    elementSize,rowSize,imageSize,myswapBytes);
7993            break;
7994          case GL_UNSIGNED_SHORT_4_4_4_4:
7995            halveImagePackedPixel3D(4,extract4444,shove4444,
7996                                    width,height,depth,usersImage,dstImage,
7997                                    elementSize,rowSize,imageSize,myswapBytes);
7998            break;
7999          case GL_UNSIGNED_SHORT_4_4_4_4_REV:
8000            halveImagePackedPixel3D(4,extract4444rev,shove4444rev,
8001                                    width,height,depth,usersImage,dstImage,
8002                                    elementSize,rowSize,imageSize,myswapBytes);
8003            break;
8004          case GL_UNSIGNED_SHORT_5_5_5_1:
8005            halveImagePackedPixel3D(4,extract5551,shove5551,
8006                                    width,height,depth,usersImage,dstImage,
8007                                    elementSize,rowSize,imageSize,myswapBytes);
8008            break;
8009          case GL_UNSIGNED_SHORT_1_5_5_5_REV:
8010            halveImagePackedPixel3D(4,extract1555rev,shove1555rev,
8011                                    width,height,depth,usersImage,dstImage,
8012                                    elementSize,rowSize,imageSize,myswapBytes);
8013            break;
8014          case GL_UNSIGNED_INT_8_8_8_8:
8015            halveImagePackedPixel3D(4,extract8888,shove8888,
8016                                    width,height,depth,usersImage,dstImage,
8017                                    elementSize,rowSize,imageSize,myswapBytes);
8018            break;
8019          case GL_UNSIGNED_INT_8_8_8_8_REV:
8020            halveImagePackedPixel3D(4,extract8888rev,shove8888rev,
8021                                    width,height,depth,usersImage,dstImage,
8022                                    elementSize,rowSize,imageSize,myswapBytes);
8023            break;
8024          case GL_UNSIGNED_INT_10_10_10_2:
8025            halveImagePackedPixel3D(4,extract1010102,shove1010102,
8026                                    width,height,depth,usersImage,dstImage,
8027                                    elementSize,rowSize,imageSize,myswapBytes);
8028            break;
8029          case GL_UNSIGNED_INT_2_10_10_10_REV:
8030            halveImagePackedPixel3D(4,extract2101010rev,shove2101010rev,
8031                                    width,height,depth,usersImage,dstImage,
8032                                    elementSize,rowSize,imageSize,myswapBytes);
8033            break;
8034          default:
8035            assert(0);
8036            break;
8037          }
8038        newWidth = width/2;
8039        newHeight = height/2;
8040        newDepth = depth/2;
8041        /* clamp to 1 */
8042        if (newWidth < 1) newWidth= 1;
8043        if (newHeight < 1) newHeight= 1;
8044        if (newDepth < 1) newDepth= 1;
8045
8046        myswapBytes = 0;
8047        rowSize = newWidth * groupSize;
8048        imageSize= rowSize * newHeight; /* 3dstuff */
8049        memReq = imageSize3D(newWidth, newHeight, newDepth, format, type);
8050        /* Swap srcImage and dstImage */
8051        __GLU_SWAP_IMAGE(srcImage,dstImage);
8052        switch(type) {
8053        case GL_UNSIGNED_BYTE:
8054          dstImage = (GLubyte *)malloc(memReq);
8055          break;
8056        case GL_BYTE:
8057          dstImage = (GLbyte *)malloc(memReq);
8058          break;
8059        case GL_UNSIGNED_SHORT:
8060          dstImage = (GLushort *)malloc(memReq);
8061          break;
8062        case GL_SHORT:
8063          dstImage = (GLshort *)malloc(memReq);
8064          break;
8065        case GL_UNSIGNED_INT:
8066          dstImage = (GLuint *)malloc(memReq);
8067          break;
8068        case GL_INT:
8069          dstImage = (GLint *)malloc(memReq);
8070          break;
8071        case GL_FLOAT:
8072          dstImage = (GLfloat *)malloc(memReq);
8073          break;
8074        case GL_UNSIGNED_BYTE_3_3_2:
8075        case GL_UNSIGNED_BYTE_2_3_3_REV:
8076          dstImage = (GLubyte *)malloc(memReq);
8077          break;
8078        case GL_UNSIGNED_SHORT_5_6_5:
8079        case GL_UNSIGNED_SHORT_5_6_5_REV:
8080        case GL_UNSIGNED_SHORT_4_4_4_4:
8081        case GL_UNSIGNED_SHORT_4_4_4_4_REV:
8082        case GL_UNSIGNED_SHORT_5_5_5_1:
8083        case GL_UNSIGNED_SHORT_1_5_5_5_REV:
8084          dstImage = (GLushort *)malloc(memReq);
8085          break;
8086        case GL_UNSIGNED_INT_8_8_8_8:
8087        case GL_UNSIGNED_INT_8_8_8_8_REV:
8088        case GL_UNSIGNED_INT_10_10_10_2:
8089        case GL_UNSIGNED_INT_2_10_10_10_REV:
8090          dstImage = (GLuint *)malloc(memReq);
8091          break;
8092        default:
8093          return GLU_INVALID_ENUM; /* assertion */
8094        }
8095        if (dstImage == NULL) {
8096          glPixelStorei(GL_UNPACK_ALIGNMENT, psm.unpack_alignment);
8097          glPixelStorei(GL_UNPACK_SKIP_ROWS, psm.unpack_skip_rows);
8098          glPixelStorei(GL_UNPACK_SKIP_PIXELS, psm.unpack_skip_pixels);
8099          glPixelStorei(GL_UNPACK_ROW_LENGTH, psm.unpack_row_length);
8100          glPixelStorei(GL_UNPACK_SWAP_BYTES, psm.unpack_swap_bytes);
8101          glPixelStorei(GL_UNPACK_SKIP_IMAGES, psm.unpack_skip_images);
8102          glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, psm.unpack_image_height);
8103          free(srcImage);
8104          return GLU_OUT_OF_MEMORY;
8105        }
8106        /* level userLevel+1 is in srcImage; level userLevel already saved */
8107        level = userLevel+1;
8108    } else {/* user's image is *not* nice power-of-2 sized square */
8109        memReq = imageSize3D(newWidth, newHeight, newDepth, format, type);
8110        switch(type) {
8111            case GL_UNSIGNED_BYTE:
8112                dstImage = (GLubyte *)malloc(memReq);
8113                break;
8114            case GL_BYTE:
8115                dstImage = (GLbyte *)malloc(memReq);
8116                break;
8117            case GL_UNSIGNED_SHORT:
8118                dstImage = (GLushort *)malloc(memReq);
8119                break;
8120            case GL_SHORT:
8121                dstImage = (GLshort *)malloc(memReq);
8122                break;
8123            case GL_UNSIGNED_INT:
8124                dstImage = (GLuint *)malloc(memReq);
8125                break;
8126            case GL_INT:
8127                dstImage = (GLint *)malloc(memReq);
8128                break;
8129            case GL_FLOAT:
8130                dstImage = (GLfloat *)malloc(memReq);
8131                break;
8132            case GL_UNSIGNED_BYTE_3_3_2:
8133            case GL_UNSIGNED_BYTE_2_3_3_REV:
8134                dstImage = (GLubyte *)malloc(memReq);
8135                break;
8136            case GL_UNSIGNED_SHORT_5_6_5:
8137            case GL_UNSIGNED_SHORT_5_6_5_REV:
8138            case GL_UNSIGNED_SHORT_4_4_4_4:
8139            case GL_UNSIGNED_SHORT_4_4_4_4_REV:
8140            case GL_UNSIGNED_SHORT_5_5_5_1:
8141            case GL_UNSIGNED_SHORT_1_5_5_5_REV:
8142                dstImage = (GLushort *)malloc(memReq);
8143                break;
8144            case GL_UNSIGNED_INT_8_8_8_8:
8145            case GL_UNSIGNED_INT_8_8_8_8_REV:
8146            case GL_UNSIGNED_INT_10_10_10_2:
8147            case GL_UNSIGNED_INT_2_10_10_10_REV:
8148                dstImage = (GLuint *)malloc(memReq);
8149                break;
8150            default:
8151                return GLU_INVALID_ENUM; /* assertion */
8152        }
8153
8154        if (dstImage == NULL) {
8155            glPixelStorei(GL_UNPACK_ALIGNMENT, psm.unpack_alignment);
8156            glPixelStorei(GL_UNPACK_SKIP_ROWS, psm.unpack_skip_rows);
8157            glPixelStorei(GL_UNPACK_SKIP_PIXELS, psm.unpack_skip_pixels);
8158            glPixelStorei(GL_UNPACK_ROW_LENGTH, psm.unpack_row_length);
8159            glPixelStorei(GL_UNPACK_SWAP_BYTES, psm.unpack_swap_bytes);
8160            glPixelStorei(GL_UNPACK_SKIP_IMAGES, psm.unpack_skip_images);
8161            glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, psm.unpack_image_height);
8162            return GLU_OUT_OF_MEMORY;
8163        }
8164        /*printf("Build3DMipmaps(): ScaleImage3D %d %d %d->%d %d %d\n",
8165        width,height,depth,newWidth,newHeight,newDepth);*/
8166
8167        gluScaleImage3D(format, width, height, depth, type, usersImage,
8168                        newWidth, newHeight, newDepth, type, dstImage);
8169
8170        myswapBytes = 0;
8171        rowSize = newWidth * groupSize;
8172        imageSize = rowSize * newHeight; /* 3dstuff */
8173        /* Swap dstImage and srcImage */
8174        __GLU_SWAP_IMAGE(srcImage,dstImage);
8175
8176        if(levels != 0) { /* use as little memory as possible */
8177          {
8178             int nextWidth= newWidth/2;
8179             int nextHeight= newHeight/2;
8180             int nextDepth= newDepth/2;
8181             if (nextWidth < 1) nextWidth= 1;
8182             if (nextHeight < 1) nextHeight= 1;  
8183             if (nextDepth < 1) nextDepth= 1;    
8184
8185          memReq = imageSize3D(nextWidth, nextHeight, nextDepth, format, type);
8186          }
8187          switch(type) {
8188          case GL_UNSIGNED_BYTE:
8189            dstImage = (GLubyte *)malloc(memReq);
8190            break;
8191          case GL_BYTE:
8192            dstImage = (GLbyte *)malloc(memReq);
8193            break;
8194          case GL_UNSIGNED_SHORT:
8195            dstImage = (GLushort *)malloc(memReq);
8196            break;
8197          case GL_SHORT:
8198            dstImage = (GLshort *)malloc(memReq);
8199            break;
8200          case GL_UNSIGNED_INT:
8201            dstImage = (GLuint *)malloc(memReq);
8202            break;
8203          case GL_INT:
8204            dstImage = (GLint *)malloc(memReq);
8205            break;
8206          case GL_FLOAT:
8207            dstImage = (GLfloat *)malloc(memReq);
8208            break;
8209          case GL_UNSIGNED_BYTE_3_3_2:
8210          case GL_UNSIGNED_BYTE_2_3_3_REV:
8211            dstImage = (GLubyte *)malloc(memReq);
8212            break;
8213          case GL_UNSIGNED_SHORT_5_6_5:
8214          case GL_UNSIGNED_SHORT_5_6_5_REV:
8215          case GL_UNSIGNED_SHORT_4_4_4_4:
8216          case GL_UNSIGNED_SHORT_4_4_4_4_REV:
8217          case GL_UNSIGNED_SHORT_5_5_5_1:
8218          case GL_UNSIGNED_SHORT_1_5_5_5_REV:
8219            dstImage = (GLushort *)malloc(memReq);
8220            break;
8221          case GL_UNSIGNED_INT_8_8_8_8:
8222          case GL_UNSIGNED_INT_8_8_8_8_REV:
8223          case GL_UNSIGNED_INT_10_10_10_2:
8224          case GL_UNSIGNED_INT_2_10_10_10_REV:
8225            dstImage = (GLuint *)malloc(memReq);
8226            break;
8227          default:
8228            return GLU_INVALID_ENUM; /* assertion */
8229          }
8230          if (dstImage == NULL) {
8231            glPixelStorei(GL_UNPACK_ALIGNMENT, psm.unpack_alignment);
8232            glPixelStorei(GL_UNPACK_SKIP_ROWS, psm.unpack_skip_rows);
8233            glPixelStorei(GL_UNPACK_SKIP_PIXELS, psm.unpack_skip_pixels);
8234            glPixelStorei(GL_UNPACK_ROW_LENGTH, psm.unpack_row_length);
8235            glPixelStorei(GL_UNPACK_SWAP_BYTES, psm.unpack_swap_bytes);
8236            glPixelStorei(GL_UNPACK_SKIP_IMAGES, psm.unpack_skip_images);
8237            glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, psm.unpack_image_height);
8238            free(srcImage);
8239            return GLU_OUT_OF_MEMORY;
8240          }
8241        }
8242        /* level userLevel is in srcImage; nothing saved yet */
8243        level = userLevel;       
8244    }
8245
8246    glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE);
8247    if (baseLevel <= level && level <= maxLevel) {
8248      gluTexImage3D(target, level, internalFormat, newWidth, newHeight, newDepth,
8249                   0,format, type, (void *)srcImage);
8250    }
8251    level++; /* update current level for the loop */
8252    for (; level <= levels; level++) {
8253        switch(type) {
8254            case GL_UNSIGNED_BYTE:
8255                if (newDepth > 1) {
8256                halveImage3D(cmpts,extractUbyte,shoveUbyte,
8257                             newWidth,newHeight,newDepth,
8258                             srcImage,dstImage,elementSize,groupSize,rowSize,
8259                             imageSize,myswapBytes);
8260                }
8261                else {
8262                  halveImage_ubyte(cmpts,newWidth,newHeight,srcImage,dstImage,
8263                                   elementSize,rowSize,groupSize);
8264                }
8265                break;
8266            case GL_BYTE:
8267                if (newDepth > 1) {
8268                halveImage3D(cmpts,extractSbyte,shoveSbyte,
8269                             newWidth,newHeight,newDepth,
8270                             srcImage,dstImage,elementSize,groupSize,rowSize,
8271                             imageSize,myswapBytes);
8272                }
8273                else {
8274                  halveImage_byte(cmpts,newWidth,newHeight,srcImage,dstImage,
8275                                   elementSize,rowSize,groupSize);
8276                }
8277                break;
8278            case GL_UNSIGNED_SHORT:
8279                if (newDepth > 1) {
8280                halveImage3D(cmpts,extractUshort,shoveUshort,
8281                             newWidth,newHeight,newDepth,
8282                             srcImage,dstImage,elementSize,groupSize,rowSize,
8283                             imageSize,myswapBytes);
8284                }
8285                else {
8286                  halveImage_ushort(cmpts,newWidth,newHeight,srcImage,dstImage,
8287                                    elementSize,rowSize,groupSize,myswapBytes);
8288                }
8289                break;
8290            case GL_SHORT:
8291                if (newDepth > 1) {
8292                halveImage3D(cmpts,extractSshort,shoveSshort,
8293                             newWidth,newHeight,newDepth,
8294                             srcImage,dstImage,elementSize,groupSize,rowSize,
8295                             imageSize,myswapBytes);
8296                }
8297                else {
8298                  halveImage_short(cmpts,newWidth,newHeight,srcImage,dstImage,
8299                                   elementSize,rowSize,groupSize,myswapBytes);
8300                }
8301                break;
8302            case GL_UNSIGNED_INT:
8303                if (newDepth > 1) {
8304                halveImage3D(cmpts,extractUint,shoveUint,
8305                             newWidth,newHeight,newDepth,
8306                             srcImage,dstImage,elementSize,groupSize,rowSize,
8307                             imageSize,myswapBytes);
8308                }
8309                else {
8310                  halveImage_uint(cmpts,newWidth,newHeight,srcImage,dstImage,
8311                                  elementSize,rowSize,groupSize,myswapBytes);
8312                }
8313                break;
8314            case GL_INT:
8315                if (newDepth > 1) {
8316                halveImage3D(cmpts,extractSint,shoveSint,
8317                             newWidth,newHeight,newDepth,
8318                             srcImage,dstImage,elementSize,groupSize,rowSize,
8319                             imageSize,myswapBytes);
8320                }
8321                else {
8322                  halveImage_int(cmpts,newWidth,newHeight,srcImage,dstImage,
8323                                 elementSize,rowSize,groupSize,myswapBytes);
8324                }
8325                break;
8326            case GL_FLOAT:
8327                if (newDepth > 1) {
8328                halveImage3D(cmpts,extractFloat,shoveFloat,
8329                             newWidth,newHeight,newDepth,
8330                             srcImage,dstImage,elementSize,groupSize,rowSize,
8331                             imageSize,myswapBytes);
8332                }
8333                else {
8334                  halveImage_float(cmpts,newWidth,newHeight,srcImage,dstImage,
8335                                   elementSize,rowSize,groupSize,myswapBytes);
8336                }
8337                break;
8338            case GL_UNSIGNED_BYTE_3_3_2:
8339                halveImagePackedPixel3D(3,extract332,shove332,
8340                                        newWidth,newHeight,newDepth,
8341                                        srcImage,dstImage,elementSize,rowSize,
8342                                        imageSize,myswapBytes);
8343                break;
8344            case GL_UNSIGNED_BYTE_2_3_3_REV:
8345                halveImagePackedPixel3D(3,extract233rev,shove233rev,
8346                                        newWidth,newHeight,newDepth,
8347                                        srcImage,dstImage,elementSize,rowSize,
8348                                        imageSize,myswapBytes);
8349                break;
8350            case GL_UNSIGNED_SHORT_5_6_5:
8351                halveImagePackedPixel3D(3,extract565,shove565,
8352                                        newWidth,newHeight,newDepth,
8353                                        srcImage,dstImage,elementSize,rowSize,
8354                                        imageSize,myswapBytes);
8355                break;
8356            case GL_UNSIGNED_SHORT_5_6_5_REV:
8357                halveImagePackedPixel3D(3,extract565rev,shove565rev,
8358                                        newWidth,newHeight,newDepth,
8359                                        srcImage,dstImage,elementSize,rowSize,
8360                                        imageSize,myswapBytes);
8361                break;
8362            case GL_UNSIGNED_SHORT_4_4_4_4:
8363                halveImagePackedPixel3D(4,extract4444,shove4444,
8364                                        newWidth,newHeight,newDepth,
8365                                        srcImage,dstImage,elementSize,rowSize,
8366                                        imageSize,myswapBytes);
8367                break;
8368            case GL_UNSIGNED_SHORT_4_4_4_4_REV:
8369                halveImagePackedPixel3D(4,extract4444rev,shove4444rev,
8370                                        newWidth,newHeight,newDepth,
8371                                        srcImage,dstImage,elementSize,rowSize,
8372                                        imageSize,myswapBytes);
8373                break;
8374            case GL_UNSIGNED_SHORT_5_5_5_1:              
8375                halveImagePackedPixel3D(4,extract5551,shove5551,
8376                                        newWidth,newHeight,newDepth,
8377                                        srcImage,dstImage,elementSize,rowSize,
8378                                        imageSize,myswapBytes);
8379                break;
8380            case GL_UNSIGNED_SHORT_1_5_5_5_REV:          
8381                halveImagePackedPixel3D(4,extract1555rev,shove1555rev,
8382                                        newWidth,newHeight,newDepth,
8383                                        srcImage,dstImage,elementSize,rowSize,
8384                                        imageSize,myswapBytes);
8385                break;
8386            case GL_UNSIGNED_INT_8_8_8_8:
8387                halveImagePackedPixel3D(4,extract8888,shove8888,
8388                                        newWidth,newHeight,newDepth,
8389                                        srcImage,dstImage,elementSize,rowSize,
8390                                        imageSize,myswapBytes);
8391                break;
8392            case GL_UNSIGNED_INT_8_8_8_8_REV:
8393                halveImagePackedPixel3D(4,extract8888rev,shove8888rev,
8394                                        newWidth,newHeight,newDepth,
8395                                        srcImage,dstImage,elementSize,rowSize,
8396                                        imageSize,myswapBytes);
8397                break;
8398            case GL_UNSIGNED_INT_10_10_10_2:
8399                halveImagePackedPixel3D(4,extract1010102,shove1010102,
8400                                        newWidth,newHeight,newDepth,
8401                                        srcImage,dstImage,elementSize,rowSize,
8402                                        imageSize,myswapBytes);
8403                break;
8404            case GL_UNSIGNED_INT_2_10_10_10_REV:
8405                halveImagePackedPixel3D(4,extract2101010rev,shove2101010rev,
8406                                        newWidth,newHeight,newDepth,
8407                                        srcImage,dstImage,elementSize,rowSize,
8408                                        imageSize,myswapBytes);
8409                break;
8410            default:
8411                assert(0);
8412                break;
8413        }
8414
8415        __GLU_SWAP_IMAGE(srcImage,dstImage);
8416
8417        if (newWidth > 1) { newWidth /= 2; rowSize /= 2;}
8418        if (newHeight > 1) { newHeight /= 2; imageSize = rowSize * newHeight; }
8419        if (newDepth > 1) newDepth /= 2;
8420        {
8421           /* call tex image with srcImage untouched since it's not padded */
8422           if (baseLevel <= level && level <= maxLevel) {
8423             gluTexImage3D(target, level, internalFormat, newWidth, newHeight,
8424                          newDepth,0, format, type, (void *) srcImage);
8425           }
8426        }
8427    } /* for level */
8428    glPixelStorei(GL_UNPACK_ALIGNMENT, psm.unpack_alignment);
8429    glPixelStorei(GL_UNPACK_SKIP_ROWS, psm.unpack_skip_rows);
8430    glPixelStorei(GL_UNPACK_SKIP_PIXELS, psm.unpack_skip_pixels);
8431    glPixelStorei(GL_UNPACK_ROW_LENGTH, psm.unpack_row_length);
8432    glPixelStorei(GL_UNPACK_SWAP_BYTES, psm.unpack_swap_bytes);
8433    glPixelStorei(GL_UNPACK_SKIP_IMAGES, psm.unpack_skip_images);
8434    glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, psm.unpack_image_height);
8435
8436    free(srcImage); /*if you get to here, a srcImage has always been malloc'ed*/
8437    if (dstImage) { /* if it's non-rectangular and only 1 level */
8438      free(dstImage);
8439    }
8440    return 0;
8441 } /* gluBuild3DMipmapLevelsCore() */
8442
8443 GLint GLAPIENTRY
8444 gluBuild3DMipmapLevels(GLenum target, GLint internalFormat,
8445                              GLsizei width, GLsizei height, GLsizei depth,
8446                              GLenum format, GLenum type,
8447                              GLint userLevel, GLint baseLevel, GLint maxLevel,
8448                              const void *data)
8449 {
8450    int level, levels;
8451
8452    int rc= checkMipmapArgs(internalFormat,format,type);
8453    if (rc != 0) return rc;
8454
8455    if (width < 1 || height < 1 || depth < 1) {
8456        return GLU_INVALID_VALUE;
8457    }
8458
8459    if(type == GL_BITMAP) {
8460       return GLU_INVALID_ENUM;
8461    }
8462
8463    levels = computeLog(width);
8464    level = computeLog(height);
8465    if (level > levels) levels=level;
8466    level = computeLog(depth);
8467    if (level > levels) levels=level;
8468
8469    levels+= userLevel;
8470    if (!isLegalLevels(userLevel,baseLevel,maxLevel,levels))
8471       return GLU_INVALID_VALUE;
8472
8473    return gluBuild3DMipmapLevelsCore(target, internalFormat,
8474                                      width, height, depth,
8475                                      width, height, depth,
8476                                      format, type,
8477                                      userLevel, baseLevel, maxLevel,
8478                                      data);
8479 } /* gluBuild3DMipmapLevels() */
8480
8481 GLint GLAPIENTRY
8482 gluBuild3DMipmaps(GLenum target, GLint internalFormat,
8483                         GLsizei width, GLsizei height, GLsizei depth,
8484                         GLenum format, GLenum type, const void *data)
8485 {
8486    GLint widthPowerOf2, heightPowerOf2, depthPowerOf2;
8487    int level, levels;
8488
8489    int rc= checkMipmapArgs(internalFormat,format,type);
8490    if (rc != 0) return rc;
8491
8492    if (width < 1 || height < 1 || depth < 1) {
8493        return GLU_INVALID_VALUE;
8494    }
8495
8496    if(type == GL_BITMAP) {
8497       return GLU_INVALID_ENUM;
8498    }
8499
8500    closestFit3D(target,width,height,depth,internalFormat,format,type,
8501                 &widthPowerOf2,&heightPowerOf2,&depthPowerOf2);
8502
8503    levels = computeLog(widthPowerOf2);
8504    level = computeLog(heightPowerOf2);
8505    if (level > levels) levels=level;
8506    level = computeLog(depthPowerOf2);
8507    if (level > levels) levels=level;
8508
8509    return gluBuild3DMipmapLevelsCore(target, internalFormat,
8510                                      width, height, depth,
8511                                      widthPowerOf2, heightPowerOf2,
8512                                      depthPowerOf2,
8513                                      format, type, 0, 0, levels,
8514                                      data);
8515 } /* gluBuild3DMipmaps() */
8516
8517 static GLdouble extractUbyte(int isSwap, const void *ubyte)
8518 {
8519    isSwap= isSwap;              /* turn off warnings */
8520
8521    assert(*((const GLubyte *)ubyte) <= 255);
8522
8523    return (GLdouble)(*((const GLubyte *)ubyte));
8524 } /* extractUbyte() */
8525
8526 static void shoveUbyte(GLdouble value, int index, void *data)
8527 {
8528    assert(0.0 <= value && value < 256.0);
8529
8530    ((GLubyte *)data)[index]= (GLubyte)value;
8531 } /* shoveUbyte() */
8532
8533 static GLdouble extractSbyte(int isSwap, const void *sbyte)
8534 {
8535    isSwap= isSwap;              /* turn off warnings */
8536
8537    assert(*((const GLbyte *)sbyte) <= 127);
8538
8539    return (GLdouble)(*((const GLbyte *)sbyte));
8540 } /* extractSbyte() */
8541
8542 static void shoveSbyte(GLdouble value, int index, void *data)
8543 {
8544    ((GLbyte *)data)[index]= (GLbyte)value;
8545 } /* shoveSbyte() */
8546
8547 static GLdouble extractUshort(int isSwap, const void *uitem)
8548 {
8549    GLushort ushort;
8550
8551    if (isSwap) {
8552      ushort= __GLU_SWAP_2_BYTES(uitem);
8553    }
8554    else {
8555      ushort= *(const GLushort *)uitem;
8556    }
8557
8558    assert(ushort <= 65535);
8559
8560    return (GLdouble)ushort;
8561 } /* extractUshort() */
8562
8563 static void shoveUshort(GLdouble value, int index, void *data)
8564 {
8565    assert(0.0 <= value && value < 65536.0);
8566
8567    ((GLushort *)data)[index]= (GLushort)value;
8568 } /* shoveUshort() */
8569
8570 static GLdouble extractSshort(int isSwap, const void *sitem)
8571 {
8572    GLshort sshort;
8573
8574    if (isSwap) {
8575      sshort= __GLU_SWAP_2_BYTES(sitem);
8576    }
8577    else {
8578      sshort= *(const GLshort *)sitem;
8579    }
8580
8581    assert(sshort <= 32767);
8582
8583    return (GLdouble)sshort;
8584 } /* extractSshort() */
8585
8586 static void shoveSshort(GLdouble value, int index, void *data)
8587 {
8588    assert(0.0 <= value && value < 32768.0);
8589
8590    ((GLshort *)data)[index]= (GLshort)value;
8591 } /* shoveSshort() */
8592
8593 static GLdouble extractUint(int isSwap, const void *uitem)
8594 {
8595    GLuint uint;
8596
8597    if (isSwap) {
8598      uint= __GLU_SWAP_4_BYTES(uitem);
8599    }
8600    else {
8601      uint= *(const GLuint *)uitem;
8602    }
8603
8604    assert(uint <= 0xffffffff);
8605
8606    return (GLdouble)uint;
8607 } /* extractUint() */
8608
8609 static void shoveUint(GLdouble value, int index, void *data)
8610 {
8611    assert(0.0 <= value && value <= (GLdouble) UINT_MAX);
8612
8613    ((GLuint *)data)[index]= (GLuint)value;
8614 } /* shoveUint() */
8615
8616 static GLdouble extractSint(int isSwap, const void *sitem)
8617 {
8618    GLint sint;
8619
8620    if (isSwap) {
8621      sint= __GLU_SWAP_4_BYTES(sitem);
8622    }
8623    else {
8624      sint= *(const GLint *)sitem;
8625    }
8626
8627    assert(sint <= 0x7fffffff);
8628
8629    return (GLdouble)sint;
8630 } /* extractSint() */
8631
8632 static void shoveSint(GLdouble value, int index, void *data)
8633 {
8634    assert(0.0 <= value && value <= (GLdouble) INT_MAX);
8635
8636    ((GLint *)data)[index]= (GLint)value;
8637 } /* shoveSint() */
8638
8639 static GLdouble extractFloat(int isSwap, const void *item)
8640 {
8641    GLfloat ffloat;
8642
8643    if (isSwap) {
8644      ffloat= __GLU_SWAP_4_BYTES(item);
8645    }
8646    else {
8647      ffloat= *(const GLfloat *)item;
8648    }
8649
8650    assert(ffloat <= 1.0);
8651
8652    return (GLdouble)ffloat;
8653 } /* extractFloat() */
8654
8655 static void shoveFloat(GLdouble value, int index, void *data)
8656 {
8657    assert(0.0 <= value && value <= 1.0);
8658
8659    ((GLfloat *)data)[index]= value;
8660 } /* shoveFloat() */
8661
8662 static void halveImageSlice(int components,
8663                             GLdouble (*extract)(int, const void *),
8664                             void (*shove)(GLdouble, int, void *),
8665                             GLint width, GLint height, GLint depth,
8666                             const void *dataIn, void *dataOut,
8667                             GLint elementSizeInBytes,
8668                             GLint groupSizeInBytes,
8669                             GLint rowSizeInBytes,
8670                             GLint imageSizeInBytes,
8671                             GLint isSwap)
8672 {
8673    int ii, jj;
8674    int halfWidth= width / 2;
8675    int halfHeight= height / 2;
8676    int halfDepth= depth / 2;
8677    const char *src= (const char *)dataIn;
8678    int rowPadBytes= rowSizeInBytes - (width * groupSizeInBytes);
8679    int imagePadBytes= imageSizeInBytes - (width*height*groupSizeInBytes);
8680    int outIndex= 0;
8681
8682    assert((width == 1 || height == 1) && depth >= 2);
8683
8684    if (width == height) {       /* a 1-pixel column viewed from top */
8685       /* printf("1-column\n");*/
8686       assert(width == 1 && height == 1);
8687       assert(depth >= 2);
8688
8689       for (ii= 0; ii< halfDepth; ii++) {
8690          int cc;
8691
8692          for (cc = 0; cc < components; cc++) {
8693             double totals[4];
8694             double extractTotals[BOX2][4];
8695             int kk;
8696
8697             extractTotals[0][cc]= (*extract)(isSwap,src);
8698             extractTotals[1][cc]= (*extract)(isSwap,(src+imageSizeInBytes));
8699
8700             /* average 2 pixels since only a column */
8701             totals[cc]= 0.0;
8702             /* totals[RED]= extractTotals[0][RED]+extractTotals[1][RED];
8703              * totals[RED]/= 2.0;
8704              */
8705             for (kk = 0; kk < BOX2; kk++) {
8706               totals[cc]+= extractTotals[kk][cc];
8707             }
8708             totals[cc]/= (double)BOX2;
8709
8710             (*shove)(totals[cc],outIndex,dataOut);
8711             outIndex++;
8712             src+= elementSizeInBytes;
8713          } /* for cc */
8714
8715          /* skip over to next group of 2 */
8716          src+= rowSizeInBytes;
8717       } /* for ii */
8718
8719       assert(src == &((const char *)dataIn)[rowSizeInBytes*height*depth]);
8720       assert(outIndex == halfDepth * components);
8721    }
8722    else if (height == 1) {      /* horizontal slice viewed from top */
8723       /* printf("horizontal slice\n"); */
8724       assert(width != 1);
8725
8726       for (ii= 0; ii< halfDepth; ii++) {
8727          for (jj= 0; jj< halfWidth; jj++) {
8728             int cc;
8729
8730             for (cc = 0; cc < components; cc++) {
8731                int kk;
8732                double totals[4];
8733                double extractTotals[BOX4][4];
8734
8735                extractTotals[0][cc]=(*extract)(isSwap,src);
8736                extractTotals[1][cc]=(*extract)(isSwap,
8737                                                (src+groupSizeInBytes));
8738                extractTotals[2][cc]=(*extract)(isSwap,
8739                                                (src+imageSizeInBytes));
8740                extractTotals[3][cc]=(*extract)(isSwap,
8741                                                (src+imageSizeInBytes+groupSizeInBytes));
8742
8743                /* grab 4 pixels to average */
8744                totals[cc]= 0.0;
8745                /* totals[RED]= extractTotals[0][RED]+extractTotals[1][RED]+
8746                 *              extractTotals[2][RED]+extractTotals[3][RED];
8747                 * totals[RED]/= 4.0;
8748                 */
8749                for (kk = 0; kk < BOX4; kk++) {
8750                   totals[cc]+= extractTotals[kk][cc];
8751                }
8752                totals[cc]/= (double)BOX4;
8753
8754                (*shove)(totals[cc],outIndex,dataOut);
8755                outIndex++;
8756
8757                src+= elementSizeInBytes;
8758             } /* for cc */
8759
8760             /* skip over to next horizontal square of 4 */
8761             src+= groupSizeInBytes;
8762          } /* for jj */
8763          src+= rowPadBytes;
8764
8765          src+= rowSizeInBytes;
8766       } /* for ii */
8767
8768       assert(src == &((const char *)dataIn)[rowSizeInBytes*height*depth]);
8769       assert(outIndex == halfWidth * halfDepth * components);
8770    }
8771    else if (width == 1) {       /* vertical slice viewed from top */
8772       /* printf("vertical slice\n"); */
8773       assert(height != 1);
8774
8775       for (ii= 0; ii< halfDepth; ii++) {
8776          for (jj= 0; jj< halfHeight; jj++) {
8777             int cc;
8778
8779             for (cc = 0; cc < components; cc++) {
8780                int kk;
8781                double totals[4];
8782                double extractTotals[BOX4][4];
8783
8784                extractTotals[0][cc]=(*extract)(isSwap,src);
8785                extractTotals[1][cc]=(*extract)(isSwap,
8786                                                (src+rowSizeInBytes));
8787                extractTotals[2][cc]=(*extract)(isSwap,
8788                                                (src+imageSizeInBytes));
8789                extractTotals[3][cc]=(*extract)(isSwap,
8790                                                (src+imageSizeInBytes+rowSizeInBytes));
8791
8792                /* grab 4 pixels to average */
8793                totals[cc]= 0.0;
8794                /* totals[RED]= extractTotals[0][RED]+extractTotals[1][RED]+
8795                 *              extractTotals[2][RED]+extractTotals[3][RED];
8796                 * totals[RED]/= 4.0;
8797                 */
8798                for (kk = 0; kk < BOX4; kk++) {
8799                   totals[cc]+= extractTotals[kk][cc];
8800                }
8801                totals[cc]/= (double)BOX4;
8802
8803                (*shove)(totals[cc],outIndex,dataOut);
8804                outIndex++;
8805
8806                src+= elementSizeInBytes;
8807             } /* for cc */
8808             src+= rowPadBytes;
8809
8810             /* skip over to next vertical square of 4 */
8811             src+= rowSizeInBytes;
8812          } /* for jj */
8813          src+= imagePadBytes;
8814
8815          src+= imageSizeInBytes;
8816       } /* for ii */
8817
8818       assert(src == &((const char *)dataIn)[rowSizeInBytes*height*depth]);
8819       assert(outIndex == halfHeight * halfDepth * components);
8820    }
8821
8822 } /* halveImageSlice() */
8823
8824 static void halveImage3D(int components,
8825                          GLdouble (*extract)(int, const void *),
8826                          void (*shove)(GLdouble, int, void *),
8827                          GLint width, GLint height, GLint depth,
8828                          const void *dataIn, void *dataOut,
8829                          GLint elementSizeInBytes,
8830                          GLint groupSizeInBytes,
8831                          GLint rowSizeInBytes,
8832                          GLint imageSizeInBytes,
8833                          GLint isSwap)
8834 {
8835    assert(depth > 1);
8836
8837    /* a horizontal/vertical/one-column slice viewed from top */
8838    if (width == 1 || height == 1) {
8839       assert(1 <= depth);
8840
8841       halveImageSlice(components,extract,shove, width, height, depth,
8842                       dataIn, dataOut, elementSizeInBytes, groupSizeInBytes,
8843                       rowSizeInBytes, imageSizeInBytes, isSwap);
8844       return;
8845    }
8846    {
8847       int ii, jj, dd;
8848
8849       int halfWidth= width / 2;
8850       int halfHeight= height / 2;
8851       int halfDepth= depth / 2;
8852       const char *src= (const char *) dataIn;
8853       int rowPadBytes= rowSizeInBytes - (width*groupSizeInBytes);
8854       int imagePadBytes= imageSizeInBytes - (width*height*groupSizeInBytes);
8855       int outIndex= 0;
8856
8857       for (dd= 0; dd < halfDepth; dd++) {
8858          for (ii= 0; ii< halfHeight; ii++) {
8859             for (jj= 0; jj< halfWidth; jj++) {
8860                int cc;
8861
8862                for (cc= 0; cc < components; cc++) {
8863                   int kk;
8864 #define BOX8 8
8865                   double totals[4];     /* 4 is maximum components */
8866                   double extractTotals[BOX8][4]; /* 4 is maximum components */
8867
8868                   extractTotals[0][cc]= (*extract)(isSwap,src);
8869                   extractTotals[1][cc]= (*extract)(isSwap,
8870                                                    (src+groupSizeInBytes));
8871                   extractTotals[2][cc]= (*extract)(isSwap,
8872                                                    (src+rowSizeInBytes));
8873                   extractTotals[3][cc]= (*extract)(isSwap,
8874                                                    (src+rowSizeInBytes+groupSizeInBytes));
8875
8876                   extractTotals[4][cc]= (*extract)(isSwap,
8877                                                    (src+imageSizeInBytes));
8878
8879                   extractTotals[5][cc]= (*extract)(isSwap,
8880                                                    (src+groupSizeInBytes+imageSizeInBytes));
8881                   extractTotals[6][cc]= (*extract)(isSwap,
8882                                                    (src+rowSizeInBytes+imageSizeInBytes));
8883                   extractTotals[7][cc]= (*extract)(isSwap,
8884                                                    (src+rowSizeInBytes+groupSizeInBytes+imageSizeInBytes));
8885
8886                   totals[cc]= 0.0;
8887
8888                   /* totals[RED]= extractTotals[0][RED]+extractTotals[1][RED]+
8889                    *              extractTotals[2][RED]+extractTotals[3][RED]+
8890                    *              extractTotals[4][RED]+extractTotals[5][RED]+
8891                    *              extractTotals[6][RED]+extractTotals[7][RED];
8892                    * totals[RED]/= 8.0;
8893                    */
8894                   for (kk = 0; kk < BOX8; kk++) {
8895                      totals[cc]+= extractTotals[kk][cc];
8896                   }
8897                   totals[cc]/= (double)BOX8;
8898
8899                   (*shove)(totals[cc],outIndex,dataOut);
8900
8901                   outIndex++;
8902
8903                   src+= elementSizeInBytes; /* go to next component */
8904                } /* for cc */
8905
8906                /* skip over to next square of 4 */
8907                src+= groupSizeInBytes;
8908             } /* for jj */
8909             /* skip past pad bytes, if any, to get to next row */
8910             src+= rowPadBytes;
8911
8912             /* src is at beginning of a row here, but it's the second row of
8913              * the square block of 4 pixels that we just worked on so we
8914              * need to go one more row.
8915              * i.e.,
8916              *                   OO...
8917              *           here -->OO...
8918              *       but want -->OO...
8919              *                   OO...
8920              *                   ...
8921              */
8922             src+= rowSizeInBytes;
8923          } /* for ii */
8924
8925          /* skip past pad bytes, if any, to get to next image */
8926          src+= imagePadBytes;
8927
8928          src+= imageSizeInBytes;
8929       } /* for dd */
8930
8931       /* both pointers must reach one byte after the end */
8932       assert(src == &((const char *)dataIn)[rowSizeInBytes*height*depth]);
8933       assert(outIndex == halfWidth * halfHeight * halfDepth * components);
8934    }
8935 } /* halveImage3D() */
8936
8937
8938
8939 /*** mipmap.c ***/
8940