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
40typedef 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 */
51typedef 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
71static int gluBuild1DMipmapLevelsCore(GLenum, GLint,
72				      GLsizei,
73				      GLsizei,
74				      GLenum, GLenum, GLint, GLint, GLint,
75				      const void *);
76static int gluBuild2DMipmapLevelsCore(GLenum, GLint,
77				      GLsizei, GLsizei,
78				      GLsizei, GLsizei,
79				      GLenum, GLenum, GLint, GLint, GLint,
80				      const void *);
81static 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 */
90static GLfloat bytes_per_element(GLenum type);
91static GLint elements_per_group(GLenum format, GLenum type);
92static GLint is_index(GLenum format);
93static GLint image_size(GLint width, GLint height, GLenum format, GLenum type);
94static void fill_image(const PixelStorageModes *,
95		       GLint width, GLint height, GLenum format,
96		       GLenum type, GLboolean index_format,
97		       const void *userdata, GLushort *newimage);
98static void empty_image(const PixelStorageModes *,
99			GLint width, GLint height, GLenum format,
100			GLenum type, GLboolean index_format,
101			const GLushort *oldimage, void *userdata);
102static void scale_internal(GLint components, GLint widthin, GLint heightin,
103			   const GLushort *datain,
104			   GLint widthout, GLint heightout,
105			   GLushort *dataout);
106
107static 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);
112static 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);
117static 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);
123static 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);
129static 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);
135static 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);
141static 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
148static int checkMipmapArgs(GLenum, GLenum, GLenum);
149static GLboolean legalFormat(GLenum);
150static GLboolean legalType(GLenum);
151static GLboolean isTypePackedPixel(GLenum);
152static GLboolean isLegalFormatForPackedPixelType(GLenum, GLenum);
153static GLboolean isLegalLevels(GLint, GLint, GLint, GLint);
154static void closestFit(GLenum, GLint, GLint, GLint, GLenum, GLenum,
155		       GLint *, GLint *);
156
157/* all extract/shove routines must return double to handle unsigned ints */
158static GLdouble extractUbyte(int, const void *);
159static void shoveUbyte(GLdouble, int, void *);
160static GLdouble extractSbyte(int, const void *);
161static void shoveSbyte(GLdouble, int, void *);
162static GLdouble extractUshort(int, const void *);
163static void shoveUshort(GLdouble, int, void *);
164static GLdouble extractSshort(int, const void *);
165static void shoveSshort(GLdouble, int, void *);
166static GLdouble extractUint(int, const void *);
167static void shoveUint(GLdouble, int, void *);
168static GLdouble extractSint(int, const void *);
169static void shoveSint(GLdouble, int, void *);
170static GLdouble extractFloat(int, const void *);
171static void shoveFloat(GLdouble, int, void *);
172static 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);
177static 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 */
184static void extract332(int,const void *, GLfloat []);
185static void shove332(const GLfloat [],int ,void *);
186static void extract233rev(int,const void *, GLfloat []);
187static void shove233rev(const GLfloat [],int ,void *);
188static void extract565(int,const void *, GLfloat []);
189static void shove565(const GLfloat [],int ,void *);
190static void extract565rev(int,const void *, GLfloat []);
191static void shove565rev(const GLfloat [],int ,void *);
192static void extract4444(int,const void *, GLfloat []);
193static void shove4444(const GLfloat [],int ,void *);
194static void extract4444rev(int,const void *, GLfloat []);
195static void shove4444rev(const GLfloat [],int ,void *);
196static void extract5551(int,const void *, GLfloat []);
197static void shove5551(const GLfloat [],int ,void *);
198static void extract1555rev(int,const void *, GLfloat []);
199static void shove1555rev(const GLfloat [],int ,void *);
200static void extract8888(int,const void *, GLfloat []);
201static void shove8888(const GLfloat [],int ,void *);
202static void extract8888rev(int,const void *, GLfloat []);
203static void shove8888rev(const GLfloat [],int ,void *);
204static void extract1010102(int,const void *, GLfloat []);
205static void shove1010102(const GLfloat [],int ,void *);
206static void extract2101010rev(int,const void *, GLfloat []);
207static void shove2101010rev(const GLfloat [],int ,void *);
208static 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);
213static 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);
218static 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
224static void halve1Dimage_ubyte(GLint, GLuint, GLuint,const GLubyte *,
225			       GLubyte *, GLint, GLint, GLint);
226static void halve1Dimage_byte(GLint, GLuint, GLuint,const GLbyte *, GLbyte *,
227			      GLint, GLint, GLint);
228static void halve1Dimage_ushort(GLint, GLuint, GLuint, const GLushort *,
229				GLushort *, GLint, GLint, GLint, GLint);
230static void halve1Dimage_short(GLint, GLuint, GLuint,const GLshort *, GLshort *,
231			       GLint, GLint, GLint, GLint);
232static void halve1Dimage_uint(GLint, GLuint, GLuint, const GLuint *, GLuint *,
233			      GLint, GLint, GLint, GLint);
234static void halve1Dimage_int(GLint, GLuint, GLuint, const GLint *, GLint *,
235			     GLint, GLint, GLint, GLint);
236static void halve1Dimage_float(GLint, GLuint, GLuint, const GLfloat *, GLfloat *,
237			       GLint, GLint, GLint, GLint);
238
239static GLint imageSize3D(GLint, GLint, GLint, GLenum,GLenum);
240static void fillImage3D(const PixelStorageModes *, GLint, GLint, GLint,GLenum,
241			GLenum, GLboolean, const void *, GLushort *);
242static void emptyImage3D(const PixelStorageModes *,
243			 GLint, GLint, GLint, GLenum,
244			 GLenum, GLboolean,
245			 const GLushort *, void *);
246static void scaleInternal3D(GLint, GLint, GLint, GLint, const GLushort *,
247			    GLint, GLint, GLint, GLushort *);
248
249static 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
266static 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
287static 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*/
311static 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
339static 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
368static 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/* */
410static 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
469static 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
511static 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
569static 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
627static 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
708static 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
773static 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
854static 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/* */
919static 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
999static 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/* */
1065static 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
1146static 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/* */
1211static 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
1289static 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
1385static 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
1602static 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
1819static 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
2099static 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
2393static 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
2680static 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
2976static 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
3270static 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
3286static 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
3309static 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/* */
3339static 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 */
3361static 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
3393static 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 */
3410static 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
3485noProxyTextures:
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
3497GLint GLAPIENTRY
3498gluScaleImage(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
3547int 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
3642GLint GLAPIENTRY
3643gluBuild1DMipmapLevels(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
3671GLint GLAPIENTRY
3672gluBuild1DMipmaps(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
3696static 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
3802static 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	     free(srcImage);
4513	     free(dstImage);
4514	     return GLU_OUT_OF_MEMORY;
4515	  }
4516
4517	  /* copy image from srcImage into newMipmapImage by rows */
4518	  for (ii= 0,
4519	       dstTrav= (unsigned char *) newMipmapImage,
4520	       srcTrav= (unsigned char *) srcImage;
4521	       ii< newheight;
4522	       ii++,
4523	       dstTrav+= newRowLength, /* make sure the correct distance... */
4524	       srcTrav+= rowsize) {    /* ...is skipped */
4525	     memcpy(dstTrav,srcTrav,rowsize);
4526	     /* note that the pad bytes are not visited and will contain
4527	      * garbage, which is ok.
4528	      */
4529	  }
4530
4531	  /* ...and use this new image for mipmapping instead */
4532	  if (baseLevel <= level && level <= maxLevel) {
4533	  glTexImage2D(target, level, internalFormat, newwidth, newheight, 0,
4534		       format, type, newMipmapImage);
4535	  }
4536	  free(newMipmapImage); /* don't forget to free it! */
4537       } /* else */
4538      }
4539    } /* for level */
4540    glPixelStorei(GL_UNPACK_ALIGNMENT, psm.unpack_alignment);
4541    glPixelStorei(GL_UNPACK_SKIP_ROWS, psm.unpack_skip_rows);
4542    glPixelStorei(GL_UNPACK_SKIP_PIXELS, psm.unpack_skip_pixels);
4543    glPixelStorei(GL_UNPACK_ROW_LENGTH, psm.unpack_row_length);
4544    glPixelStorei(GL_UNPACK_SWAP_BYTES, psm.unpack_swap_bytes);
4545
4546    free(srcImage); /*if you get to here, a srcImage has always been malloc'ed*/
4547    if (dstImage) { /* if it's non-rectangular and only 1 level */
4548      free(dstImage);
4549    }
4550    return 0;
4551} /* gluBuild2DMipmapLevelsCore() */
4552
4553GLint GLAPIENTRY
4554gluBuild2DMipmapLevels(GLenum target, GLint internalFormat,
4555			     GLsizei width, GLsizei height,
4556			     GLenum format, GLenum type,
4557			     GLint userLevel, GLint baseLevel, GLint maxLevel,
4558			     const void *data)
4559{
4560   int level, levels;
4561
4562   int rc= checkMipmapArgs(internalFormat,format,type);
4563   if (rc != 0) return rc;
4564
4565   if (width < 1 || height < 1) {
4566       return GLU_INVALID_VALUE;
4567   }
4568
4569   levels = computeLog(width);
4570   level = computeLog(height);
4571   if (level > levels) levels=level;
4572
4573   levels+= userLevel;
4574   if (!isLegalLevels(userLevel,baseLevel,maxLevel,levels))
4575      return GLU_INVALID_VALUE;
4576
4577   return gluBuild2DMipmapLevelsCore(target, internalFormat,
4578				     width, height,
4579				     width, height,
4580				     format, type,
4581				     userLevel, baseLevel, maxLevel,
4582				     data);
4583} /* gluBuild2DMipmapLevels() */
4584
4585GLint GLAPIENTRY
4586gluBuild2DMipmaps(GLenum target, GLint internalFormat,
4587			GLsizei width, GLsizei height,
4588			GLenum format, GLenum type,
4589			const void *data)
4590{
4591   GLint widthPowerOf2, heightPowerOf2;
4592   int level, levels;
4593
4594   int rc= checkMipmapArgs(internalFormat,format,type);
4595   if (rc != 0) return rc;
4596
4597   if (width < 1 || height < 1) {
4598       return GLU_INVALID_VALUE;
4599   }
4600
4601   closestFit(target,width,height,internalFormat,format,type,
4602	      &widthPowerOf2,&heightPowerOf2);
4603
4604   levels = computeLog(widthPowerOf2);
4605   level = computeLog(heightPowerOf2);
4606   if (level > levels) levels=level;
4607
4608   return gluBuild2DMipmapLevelsCore(target,internalFormat,
4609				     width, height,
4610				     widthPowerOf2,heightPowerOf2,
4611				     format,type,
4612				     0,0,levels,data);
4613}  /* gluBuild2DMipmaps() */
4614
4615#if 0
4616/*
4617** This routine is for the limited case in which
4618**	type == GL_UNSIGNED_BYTE && format != index  &&
4619**	unpack_alignment = 1 && unpack_swap_bytes == false
4620**
4621** so all of the work data can be kept as ubytes instead of shorts.
4622*/
4623static int fastBuild2DMipmaps(const PixelStorageModes *psm,
4624		       GLenum target, GLint components, GLint width,
4625		     GLint height, GLenum format,
4626		     GLenum type, void *data)
4627{
4628    GLint newwidth, newheight;
4629    GLint level, levels;
4630    GLubyte *newImage;
4631    GLint newImage_width;
4632    GLint newImage_height;
4633    GLubyte *otherImage;
4634    GLubyte *imageTemp;
4635    GLint memreq;
4636    GLint cmpts;
4637
4638
4639#if 0
4640    glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxsize);
4641    newwidth = nearestPower(width);
4642    if (newwidth > maxsize) newwidth = maxsize;
4643    newheight = nearestPower(height);
4644    if (newheight > maxsize) newheight = maxsize;
4645#else
4646    closestFit(target,width,height,components,format,type,
4647	       &newwidth,&newheight);
4648#endif
4649    levels = computeLog(newwidth);
4650    level = computeLog(newheight);
4651    if (level > levels) levels=level;
4652
4653    cmpts = elements_per_group(format,type);
4654
4655    otherImage = NULL;
4656    /**
4657    ** No need to copy the user data if its in the packed correctly.
4658    ** Make sure that later routines don't change that data.
4659    */
4660    if (psm->unpack_skip_rows == 0 && psm->unpack_skip_pixels == 0) {
4661	newImage = (GLubyte *)data;
4662	newImage_width = width;
4663	newImage_height = height;
4664    } else {
4665	GLint rowsize;
4666	GLint groups_per_line;
4667	GLint elements_per_line;
4668	const GLubyte *start;
4669	const GLubyte *iter;
4670	GLubyte *iter2;
4671	GLint i, j;
4672
4673	newImage = (GLubyte *)
4674	    malloc(image_size(width, height, format, GL_UNSIGNED_BYTE));
4675	newImage_width = width;
4676	newImage_height = height;
4677	if (newImage == NULL) {
4678	    return GLU_OUT_OF_MEMORY;
4679	}
4680
4681	/*
4682	** Abbreviated version of fill_image for this restricted case.
4683	*/
4684	if (psm->unpack_row_length > 0) {
4685	    groups_per_line = psm->unpack_row_length;
4686	} else {
4687	    groups_per_line = width;
4688	}
4689	rowsize = groups_per_line * cmpts;
4690	elements_per_line = width * cmpts;
4691	start = (const GLubyte *) data + psm->unpack_skip_rows * rowsize +
4692		psm->unpack_skip_pixels * cmpts;
4693	iter2 = newImage;
4694
4695	for (i = 0; i < height; i++) {
4696	    iter = start;
4697	    for (j = 0; j < elements_per_line; j++) {
4698		*iter2 = *iter;
4699		iter++;
4700		iter2++;
4701	    }
4702	    start += rowsize;
4703	}
4704    }
4705
4706
4707    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
4708    glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
4709    glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
4710    glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
4711    glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE);
4712
4713    for (level = 0; level <= levels; level++) {
4714	if (newImage_width == newwidth && newImage_height == newheight) {
4715	    /* Use newImage for this level */
4716	    glTexImage2D(target, level, components, newImage_width,
4717		    newImage_height, 0, format, GL_UNSIGNED_BYTE,
4718		    (void *) newImage);
4719	} else {
4720	    if (otherImage == NULL) {
4721		memreq =
4722		    image_size(newwidth, newheight, format, GL_UNSIGNED_BYTE);
4723		otherImage = (GLubyte *) malloc(memreq);
4724		if (otherImage == NULL) {
4725		    glPixelStorei(GL_UNPACK_ALIGNMENT, psm->unpack_alignment);
4726		    glPixelStorei(GL_UNPACK_SKIP_ROWS, psm->unpack_skip_rows);
4727		    glPixelStorei(GL_UNPACK_SKIP_PIXELS, psm->unpack_skip_pixels);
4728		    glPixelStorei(GL_UNPACK_ROW_LENGTH,psm->unpack_row_length);
4729		    glPixelStorei(GL_UNPACK_SWAP_BYTES,psm->unpack_swap_bytes);
4730		    return GLU_OUT_OF_MEMORY;
4731		}
4732	    }
4733/*
4734	    scale_internal_ubyte(cmpts, newImage_width, newImage_height,
4735		    newImage, newwidth, newheight, otherImage);
4736*/
4737	    /* Swap newImage and otherImage */
4738	    imageTemp = otherImage;
4739	    otherImage = newImage;
4740	    newImage = imageTemp;
4741
4742	    newImage_width = newwidth;
4743	    newImage_height = newheight;
4744	    glTexImage2D(target, level, components, newImage_width,
4745		    newImage_height, 0, format, GL_UNSIGNED_BYTE,
4746		    (void *) newImage);
4747	}
4748	if (newwidth > 1) newwidth /= 2;
4749	if (newheight > 1) newheight /= 2;
4750    }
4751    glPixelStorei(GL_UNPACK_ALIGNMENT, psm->unpack_alignment);
4752    glPixelStorei(GL_UNPACK_SKIP_ROWS, psm->unpack_skip_rows);
4753    glPixelStorei(GL_UNPACK_SKIP_PIXELS, psm->unpack_skip_pixels);
4754    glPixelStorei(GL_UNPACK_ROW_LENGTH, psm->unpack_row_length);
4755    glPixelStorei(GL_UNPACK_SWAP_BYTES, psm->unpack_swap_bytes);
4756
4757    if (newImage != (const GLubyte *)data) {
4758	free((GLbyte *) newImage);
4759    }
4760    if (otherImage && otherImage != (const GLubyte *)data) {
4761	free((GLbyte *) otherImage);
4762    }
4763    return 0;
4764}
4765#endif
4766
4767/*
4768 * Utility Routines
4769 */
4770static GLint elements_per_group(GLenum format, GLenum type)
4771{
4772    /*
4773     * Return the number of elements per group of a specified format
4774     */
4775
4776    /* If the type is packedpixels then answer is 1 (ignore format) */
4777    if (type == GL_UNSIGNED_BYTE_3_3_2 ||
4778	type == GL_UNSIGNED_BYTE_2_3_3_REV ||
4779	type == GL_UNSIGNED_SHORT_5_6_5 ||
4780	type == GL_UNSIGNED_SHORT_5_6_5_REV ||
4781	type == GL_UNSIGNED_SHORT_4_4_4_4 ||
4782	type == GL_UNSIGNED_SHORT_4_4_4_4_REV ||
4783	type == GL_UNSIGNED_SHORT_5_5_5_1  ||
4784	type == GL_UNSIGNED_SHORT_1_5_5_5_REV  ||
4785	type == GL_UNSIGNED_INT_8_8_8_8 ||
4786	type == GL_UNSIGNED_INT_8_8_8_8_REV ||
4787	type == GL_UNSIGNED_INT_10_10_10_2 ||
4788	type == GL_UNSIGNED_INT_2_10_10_10_REV) {
4789	return 1;
4790    }
4791
4792    /* Types are not packed pixels, so get elements per group */
4793    switch(format) {
4794      case GL_RGB:
4795      case GL_BGR:
4796	return 3;
4797      case GL_LUMINANCE_ALPHA:
4798	return 2;
4799      case GL_RGBA:
4800      case GL_BGRA:
4801	return 4;
4802      default:
4803	return 1;
4804    }
4805}
4806
4807static GLfloat bytes_per_element(GLenum type)
4808{
4809    /*
4810     * Return the number of bytes per element, based on the element type
4811     */
4812    switch(type) {
4813      case GL_BITMAP:
4814	return 1.0 / 8.0;
4815      case GL_UNSIGNED_SHORT:
4816	return(sizeof(GLushort));
4817      case GL_SHORT:
4818	return(sizeof(GLshort));
4819      case GL_UNSIGNED_BYTE:
4820	return(sizeof(GLubyte));
4821      case GL_BYTE:
4822	return(sizeof(GLbyte));
4823      case GL_INT:
4824	return(sizeof(GLint));
4825      case GL_UNSIGNED_INT:
4826	return(sizeof(GLuint));
4827      case GL_FLOAT:
4828	return(sizeof(GLfloat));
4829      case GL_UNSIGNED_BYTE_3_3_2:
4830      case GL_UNSIGNED_BYTE_2_3_3_REV:
4831	return(sizeof(GLubyte));
4832      case GL_UNSIGNED_SHORT_5_6_5:
4833      case GL_UNSIGNED_SHORT_5_6_5_REV:
4834      case GL_UNSIGNED_SHORT_4_4_4_4:
4835      case GL_UNSIGNED_SHORT_4_4_4_4_REV:
4836      case GL_UNSIGNED_SHORT_5_5_5_1:
4837      case GL_UNSIGNED_SHORT_1_5_5_5_REV:
4838	return(sizeof(GLushort));
4839      case GL_UNSIGNED_INT_8_8_8_8:
4840      case GL_UNSIGNED_INT_8_8_8_8_REV:
4841      case GL_UNSIGNED_INT_10_10_10_2:
4842      case GL_UNSIGNED_INT_2_10_10_10_REV:
4843	return(sizeof(GLuint));
4844      default:
4845	return 4;
4846    }
4847}
4848
4849static GLint is_index(GLenum format)
4850{
4851    return format == GL_COLOR_INDEX || format == GL_STENCIL_INDEX;
4852}
4853
4854/*
4855** Compute memory required for internal packed array of data of given type
4856** and format.
4857*/
4858static GLint image_size(GLint width, GLint height, GLenum format, GLenum type)
4859{
4860    int bytes_per_row;
4861    int components;
4862
4863assert(width > 0);
4864assert(height > 0);
4865    components = elements_per_group(format,type);
4866    if (type == GL_BITMAP) {
4867	bytes_per_row = (width + 7) / 8;
4868    } else {
4869	bytes_per_row = bytes_per_element(type) * width;
4870    }
4871    return bytes_per_row * height * components;
4872}
4873
4874/*
4875** Extract array from user's data applying all pixel store modes.
4876** The internal format used is an array of unsigned shorts.
4877*/
4878static void fill_image(const PixelStorageModes *psm,
4879		       GLint width, GLint height, GLenum format,
4880		       GLenum type, GLboolean index_format,
4881		       const void *userdata, GLushort *newimage)
4882{
4883    GLint components;
4884    GLint element_size;
4885    GLint rowsize;
4886    GLint padding;
4887    GLint groups_per_line;
4888    GLint group_size;
4889    GLint elements_per_line;
4890    const GLubyte *start;
4891    const GLubyte *iter;
4892    GLushort *iter2;
4893    GLint i, j, k;
4894    GLint myswap_bytes;
4895
4896    myswap_bytes = psm->unpack_swap_bytes;
4897    components = elements_per_group(format,type);
4898    if (psm->unpack_row_length > 0) {
4899	groups_per_line = psm->unpack_row_length;
4900    } else {
4901	groups_per_line = width;
4902    }
4903
4904    /* All formats except GL_BITMAP fall out trivially */
4905    if (type == GL_BITMAP) {
4906	GLint bit_offset;
4907	GLint current_bit;
4908
4909	rowsize = (groups_per_line * components + 7) / 8;
4910	padding = (rowsize % psm->unpack_alignment);
4911	if (padding) {
4912	    rowsize += psm->unpack_alignment - padding;
4913	}
4914	start = (const GLubyte *) userdata + psm->unpack_skip_rows * rowsize +
4915		(psm->unpack_skip_pixels * components / 8);
4916	elements_per_line = width * components;
4917	iter2 = newimage;
4918	for (i = 0; i < height; i++) {
4919	    iter = start;
4920	    bit_offset = (psm->unpack_skip_pixels * components) % 8;
4921	    for (j = 0; j < elements_per_line; j++) {
4922		/* Retrieve bit */
4923		if (psm->unpack_lsb_first) {
4924		    current_bit = iter[0] & (1 << bit_offset);
4925		} else {
4926		    current_bit = iter[0] & (1 << (7 - bit_offset));
4927		}
4928		if (current_bit) {
4929		    if (index_format) {
4930			*iter2 = 1;
4931		    } else {
4932			*iter2 = 65535;
4933		    }
4934		} else {
4935		    *iter2 = 0;
4936		}
4937		bit_offset++;
4938		if (bit_offset == 8) {
4939		    bit_offset = 0;
4940		    iter++;
4941		}
4942		iter2++;
4943	    }
4944	    start += rowsize;
4945	}
4946    } else {
4947	element_size = bytes_per_element(type);
4948	group_size = element_size * components;
4949	if (element_size == 1) myswap_bytes = 0;
4950
4951	rowsize = groups_per_line * group_size;
4952	padding = (rowsize % psm->unpack_alignment);
4953	if (padding) {
4954	    rowsize += psm->unpack_alignment - padding;
4955	}
4956	start = (const GLubyte *) userdata + psm->unpack_skip_rows * rowsize +
4957		psm->unpack_skip_pixels * group_size;
4958	elements_per_line = width * components;
4959
4960	iter2 = newimage;
4961	for (i = 0; i < height; i++) {
4962	    iter = start;
4963	    for (j = 0; j < elements_per_line; j++) {
4964		Type_Widget widget;
4965		float extractComponents[4];
4966
4967		switch(type) {
4968		  case GL_UNSIGNED_BYTE_3_3_2:
4969		    extract332(0,iter,extractComponents);
4970		    for (k = 0; k < 3; k++) {
4971		      *iter2++ = (GLushort)(extractComponents[k]*65535);
4972		    }
4973		    break;
4974		  case GL_UNSIGNED_BYTE_2_3_3_REV:
4975		    extract233rev(0,iter,extractComponents);
4976		    for (k = 0; k < 3; k++) {
4977		      *iter2++ = (GLushort)(extractComponents[k]*65535);
4978		    }
4979		    break;
4980		  case GL_UNSIGNED_BYTE:
4981		    if (index_format) {
4982			*iter2++ = *iter;
4983		    } else {
4984			*iter2++ = (*iter) * 257;
4985		    }
4986		    break;
4987		  case GL_BYTE:
4988		    if (index_format) {
4989			*iter2++ = *((const GLbyte *) iter);
4990		    } else {
4991			/* rough approx */
4992			*iter2++ = (*((const GLbyte *) iter)) * 516;
4993		    }
4994		    break;
4995		  case GL_UNSIGNED_SHORT_5_6_5:
4996		    extract565(myswap_bytes,iter,extractComponents);
4997		    for (k = 0; k < 3; k++) {
4998		      *iter2++ = (GLushort)(extractComponents[k]*65535);
4999		    }
5000		    break;
5001		  case GL_UNSIGNED_SHORT_5_6_5_REV:
5002		    extract565rev(myswap_bytes,iter,extractComponents);
5003		    for (k = 0; k < 3; k++) {
5004		      *iter2++ = (GLushort)(extractComponents[k]*65535);
5005		    }
5006		    break;
5007		  case GL_UNSIGNED_SHORT_4_4_4_4:
5008		    extract4444(myswap_bytes,iter,extractComponents);
5009		    for (k = 0; k < 4; k++) {
5010		      *iter2++ = (GLushort)(extractComponents[k]*65535);
5011		    }
5012		    break;
5013		  case GL_UNSIGNED_SHORT_4_4_4_4_REV:
5014		    extract4444rev(myswap_bytes,iter,extractComponents);
5015		    for (k = 0; k < 4; k++) {
5016		      *iter2++ = (GLushort)(extractComponents[k]*65535);
5017		    }
5018		    break;
5019		  case GL_UNSIGNED_SHORT_5_5_5_1:
5020		    extract5551(myswap_bytes,iter,extractComponents);
5021		    for (k = 0; k < 4; k++) {
5022		      *iter2++ = (GLushort)(extractComponents[k]*65535);
5023		    }
5024		    break;
5025		  case GL_UNSIGNED_SHORT_1_5_5_5_REV:
5026		    extract1555rev(myswap_bytes,iter,extractComponents);
5027		    for (k = 0; k < 4; k++) {
5028		      *iter2++ = (GLushort)(extractComponents[k]*65535);
5029		    }
5030		    break;
5031		  case GL_UNSIGNED_SHORT:
5032		  case GL_SHORT:
5033		    if (myswap_bytes) {
5034			widget.ub[0] = iter[1];
5035			widget.ub[1] = iter[0];
5036		    } else {
5037			widget.ub[0] = iter[0];
5038			widget.ub[1] = iter[1];
5039		    }
5040		    if (type == GL_SHORT) {
5041			if (index_format) {
5042			    *iter2++ = widget.s[0];
5043			} else {
5044			    /* rough approx */
5045			    *iter2++ = widget.s[0]*2;
5046			}
5047		    } else {
5048			*iter2++ = widget.us[0];
5049		    }
5050		    break;
5051		  case GL_UNSIGNED_INT_8_8_8_8:
5052		    extract8888(myswap_bytes,iter,extractComponents);
5053		    for (k = 0; k < 4; k++) {
5054		      *iter2++ = (GLushort)(extractComponents[k]*65535);
5055		    }
5056		    break;
5057		  case GL_UNSIGNED_INT_8_8_8_8_REV:
5058		    extract8888rev(myswap_bytes,iter,extractComponents);
5059		    for (k = 0; k < 4; k++) {
5060		      *iter2++ = (GLushort)(extractComponents[k]*65535);
5061		    }
5062		    break;
5063		  case GL_UNSIGNED_INT_10_10_10_2:
5064		    extract1010102(myswap_bytes,iter,extractComponents);
5065		    for (k = 0; k < 4; k++) {
5066		      *iter2++ = (GLushort)(extractComponents[k]*65535);
5067		    }
5068		    break;
5069		  case GL_UNSIGNED_INT_2_10_10_10_REV:
5070		    extract2101010rev(myswap_bytes,iter,extractComponents);
5071		    for (k = 0; k < 4; k++) {
5072		      *iter2++ = (GLushort)(extractComponents[k]*65535);
5073		    }
5074		    break;
5075		  case GL_INT:
5076		  case GL_UNSIGNED_INT:
5077		  case GL_FLOAT:
5078		    if (myswap_bytes) {
5079			widget.ub[0] = iter[3];
5080			widget.ub[1] = iter[2];
5081			widget.ub[2] = iter[1];
5082			widget.ub[3] = iter[0];
5083		    } else {
5084			widget.ub[0] = iter[0];
5085			widget.ub[1] = iter[1];
5086			widget.ub[2] = iter[2];
5087			widget.ub[3] = iter[3];
5088		    }
5089		    if (type == GL_FLOAT) {
5090			if (index_format) {
5091			    *iter2++ = widget.f;
5092			} else {
5093			    *iter2++ = 65535 * widget.f;
5094			}
5095		    } else if (type == GL_UNSIGNED_INT) {
5096			if (index_format) {
5097			    *iter2++ = widget.ui;
5098			} else {
5099			    *iter2++ = widget.ui >> 16;
5100			}
5101		    } else {
5102			if (index_format) {
5103			    *iter2++ = widget.i;
5104			} else {
5105			    *iter2++ = widget.i >> 15;
5106			}
5107		    }
5108		    break;
5109		}
5110		iter += element_size;
5111	    } /* for j */
5112	    start += rowsize;
5113#if 1
5114	    /* want 'iter' pointing at start, not within, row for assertion
5115	     * purposes
5116	     */
5117	    iter= start;
5118#endif
5119	} /* for i */
5120
5121       /* iterators should be one byte past end */
5122       if (!isTypePackedPixel(type)) {
5123	  assert(iter2 == &newimage[width*height*components]);
5124       }
5125       else {
5126	  assert(iter2 == &newimage[width*height*
5127				    elements_per_group(format,0)]);
5128       }
5129       assert( iter == &((const GLubyte *)userdata)[rowsize*height +
5130					psm->unpack_skip_rows * rowsize +
5131					psm->unpack_skip_pixels * group_size] );
5132
5133    } /* else */
5134} /* fill_image() */
5135
5136/*
5137** Insert array into user's data applying all pixel store modes.
5138** The internal format is an array of unsigned shorts.
5139** empty_image() because it is the opposite of fill_image().
5140*/
5141static void empty_image(const PixelStorageModes *psm,
5142			GLint width, GLint height, GLenum format,
5143			GLenum type, GLboolean index_format,
5144			const GLushort *oldimage, void *userdata)
5145{
5146    GLint components;
5147    GLint element_size;
5148    GLint rowsize;
5149    GLint padding;
5150    GLint groups_per_line;
5151    GLint group_size;
5152    GLint elements_per_line;
5153    GLubyte *start;
5154    GLubyte *iter;
5155    const GLushort *iter2;
5156    GLint i, j, k;
5157    GLint myswap_bytes;
5158
5159    myswap_bytes = psm->pack_swap_bytes;
5160    components = elements_per_group(format,type);
5161    if (psm->pack_row_length > 0) {
5162	groups_per_line = psm->pack_row_length;
5163    } else {
5164	groups_per_line = width;
5165    }
5166
5167    /* All formats except GL_BITMAP fall out trivially */
5168    if (type == GL_BITMAP) {
5169	GLint bit_offset;
5170	GLint current_bit;
5171
5172	rowsize = (groups_per_line * components + 7) / 8;
5173	padding = (rowsize % psm->pack_alignment);
5174	if (padding) {
5175	    rowsize += psm->pack_alignment - padding;
5176	}
5177	start = (GLubyte *) userdata + psm->pack_skip_rows * rowsize +
5178		(psm->pack_skip_pixels * components / 8);
5179	elements_per_line = width * components;
5180	iter2 = oldimage;
5181	for (i = 0; i < height; i++) {
5182	    iter = start;
5183	    bit_offset = (psm->pack_skip_pixels * components) % 8;
5184	    for (j = 0; j < elements_per_line; j++) {
5185		if (index_format) {
5186		    current_bit = iter2[0] & 1;
5187		} else {
5188		    if (iter2[0] > 32767) {
5189			current_bit = 1;
5190		    } else {
5191			current_bit = 0;
5192		    }
5193		}
5194
5195		if (current_bit) {
5196		    if (psm->pack_lsb_first) {
5197			*iter |= (1 << bit_offset);
5198		    } else {
5199			*iter |= (1 << (7 - bit_offset));
5200		    }
5201		} else {
5202		    if (psm->pack_lsb_first) {
5203			*iter &= ~(1 << bit_offset);
5204		    } else {
5205			*iter &= ~(1 << (7 - bit_offset));
5206		    }
5207		}
5208
5209		bit_offset++;
5210		if (bit_offset == 8) {
5211		    bit_offset = 0;
5212		    iter++;
5213		}
5214		iter2++;
5215	    }
5216	    start += rowsize;
5217	}
5218    } else {
5219	float shoveComponents[4];
5220
5221	element_size = bytes_per_element(type);
5222	group_size = element_size * components;
5223	if (element_size == 1) myswap_bytes = 0;
5224
5225	rowsize = groups_per_line * group_size;
5226	padding = (rowsize % psm->pack_alignment);
5227	if (padding) {
5228	    rowsize += psm->pack_alignment - padding;
5229	}
5230	start = (GLubyte *) userdata + psm->pack_skip_rows * rowsize +
5231		psm->pack_skip_pixels * group_size;
5232	elements_per_line = width * components;
5233
5234	iter2 = oldimage;
5235	for (i = 0; i < height; i++) {
5236	    iter = start;
5237	    for (j = 0; j < elements_per_line; j++) {
5238		Type_Widget widget;
5239
5240		switch(type) {
5241		  case GL_UNSIGNED_BYTE_3_3_2:
5242		    for (k = 0; k < 3; k++) {
5243		       shoveComponents[k]= *iter2++ / 65535.0;
5244		    }
5245		    shove332(shoveComponents,0,(void *)iter);
5246		    break;
5247		  case GL_UNSIGNED_BYTE_2_3_3_REV:
5248		    for (k = 0; k < 3; k++) {
5249		       shoveComponents[k]= *iter2++ / 65535.0;
5250		    }
5251		    shove233rev(shoveComponents,0,(void *)iter);
5252		    break;
5253		  case GL_UNSIGNED_BYTE:
5254		    if (index_format) {
5255			*iter = *iter2++;
5256		    } else {
5257			*iter = *iter2++ >> 8;
5258		    }
5259		    break;
5260		  case GL_BYTE:
5261		    if (index_format) {
5262			*((GLbyte *) iter) = *iter2++;
5263		    } else {
5264			*((GLbyte *) iter) = *iter2++ >> 9;
5265		    }
5266		    break;
5267		  case GL_UNSIGNED_SHORT_5_6_5:
5268		    for (k = 0; k < 3; k++) {
5269		       shoveComponents[k]= *iter2++ / 65535.0;
5270		    }
5271		    shove565(shoveComponents,0,(void *)&widget.us[0]);
5272		    if (myswap_bytes) {
5273		       iter[0] = widget.ub[1];
5274		       iter[1] = widget.ub[0];
5275		    }
5276		    else {
5277		       *(GLushort *)iter = widget.us[0];
5278		    }
5279		    break;
5280		  case GL_UNSIGNED_SHORT_5_6_5_REV:
5281		    for (k = 0; k < 3; k++) {
5282		       shoveComponents[k]= *iter2++ / 65535.0;
5283		    }
5284		    shove565rev(shoveComponents,0,(void *)&widget.us[0]);
5285		    if (myswap_bytes) {
5286		       iter[0] = widget.ub[1];
5287		       iter[1] = widget.ub[0];
5288		    }
5289		    else {
5290		       *(GLushort *)iter = widget.us[0];
5291		    }
5292		    break;
5293		  case GL_UNSIGNED_SHORT_4_4_4_4:
5294		    for (k = 0; k < 4; k++) {
5295		       shoveComponents[k]= *iter2++ / 65535.0;
5296		    }
5297		    shove4444(shoveComponents,0,(void *)&widget.us[0]);
5298		    if (myswap_bytes) {
5299		       iter[0] = widget.ub[1];
5300		       iter[1] = widget.ub[0];
5301		    } else {
5302		       *(GLushort *)iter = widget.us[0];
5303		    }
5304		    break;
5305		  case GL_UNSIGNED_SHORT_4_4_4_4_REV:
5306		    for (k = 0; k < 4; k++) {
5307		       shoveComponents[k]= *iter2++ / 65535.0;
5308		    }
5309		    shove4444rev(shoveComponents,0,(void *)&widget.us[0]);
5310		    if (myswap_bytes) {
5311		       iter[0] = widget.ub[1];
5312		       iter[1] = widget.ub[0];
5313		    } else {
5314		       *(GLushort *)iter = widget.us[0];
5315		    }
5316		    break;
5317		  case GL_UNSIGNED_SHORT_5_5_5_1:
5318		    for (k = 0; k < 4; k++) {
5319		       shoveComponents[k]= *iter2++ / 65535.0;
5320		    }
5321		    shove5551(shoveComponents,0,(void *)&widget.us[0]);
5322		    if (myswap_bytes) {
5323		       iter[0] = widget.ub[1];
5324		       iter[1] = widget.ub[0];
5325		    } else {
5326		       *(GLushort *)iter = widget.us[0];
5327		    }
5328		    break;
5329		  case GL_UNSIGNED_SHORT_1_5_5_5_REV:
5330		    for (k = 0; k < 4; k++) {
5331		       shoveComponents[k]= *iter2++ / 65535.0;
5332		    }
5333		    shove1555rev(shoveComponents,0,(void *)&widget.us[0]);
5334		    if (myswap_bytes) {
5335		       iter[0] = widget.ub[1];
5336		       iter[1] = widget.ub[0];
5337		    } else {
5338		       *(GLushort *)iter = widget.us[0];
5339		    }
5340		    break;
5341		  case GL_UNSIGNED_SHORT:
5342		  case GL_SHORT:
5343		    if (type == GL_SHORT) {
5344			if (index_format) {
5345			    widget.s[0] = *iter2++;
5346			} else {
5347			    widget.s[0] = *iter2++ >> 1;
5348			}
5349		    } else {
5350			widget.us[0] = *iter2++;
5351		    }
5352		    if (myswap_bytes) {
5353			iter[0] = widget.ub[1];
5354			iter[1] = widget.ub[0];
5355		    } else {
5356			iter[0] = widget.ub[0];
5357			iter[1] = widget.ub[1];
5358		    }
5359		    break;
5360		  case GL_UNSIGNED_INT_8_8_8_8:
5361		    for (k = 0; k < 4; k++) {
5362		       shoveComponents[k]= *iter2++ / 65535.0;
5363		    }
5364		    shove8888(shoveComponents,0,(void *)&widget.ui);
5365		    if (myswap_bytes) {
5366			iter[3] = widget.ub[0];
5367			iter[2] = widget.ub[1];
5368			iter[1] = widget.ub[2];
5369			iter[0] = widget.ub[3];
5370		    } else {
5371			*(GLuint *)iter= widget.ui;
5372		    }
5373
5374		    break;
5375		  case GL_UNSIGNED_INT_8_8_8_8_REV:
5376		    for (k = 0; k < 4; k++) {
5377		       shoveComponents[k]= *iter2++ / 65535.0;
5378		    }
5379		    shove8888rev(shoveComponents,0,(void *)&widget.ui);
5380		    if (myswap_bytes) {
5381			iter[3] = widget.ub[0];
5382			iter[2] = widget.ub[1];
5383			iter[1] = widget.ub[2];
5384			iter[0] = widget.ub[3];
5385		    } else {
5386			*(GLuint *)iter= widget.ui;
5387		    }
5388		    break;
5389		  case GL_UNSIGNED_INT_10_10_10_2:
5390		    for (k = 0; k < 4; k++) {
5391		       shoveComponents[k]= *iter2++ / 65535.0;
5392		    }
5393		    shove1010102(shoveComponents,0,(void *)&widget.ui);
5394		    if (myswap_bytes) {
5395			iter[3] = widget.ub[0];
5396			iter[2] = widget.ub[1];
5397			iter[1] = widget.ub[2];
5398			iter[0] = widget.ub[3];
5399		    } else {
5400			*(GLuint *)iter= widget.ui;
5401		    }
5402		    break;
5403		  case GL_UNSIGNED_INT_2_10_10_10_REV:
5404		    for (k = 0; k < 4; k++) {
5405		       shoveComponents[k]= *iter2++ / 65535.0;
5406		    }
5407		    shove2101010rev(shoveComponents,0,(void *)&widget.ui);
5408		    if (myswap_bytes) {
5409			iter[3] = widget.ub[0];
5410			iter[2] = widget.ub[1];
5411			iter[1] = widget.ub[2];
5412			iter[0] = widget.ub[3];
5413		    } else {
5414			*(GLuint *)iter= widget.ui;
5415		    }
5416		    break;
5417		  case GL_INT:
5418		  case GL_UNSIGNED_INT:
5419		  case GL_FLOAT:
5420		    if (type == GL_FLOAT) {
5421			if (index_format) {
5422			    widget.f = *iter2++;
5423			} else {
5424			    widget.f = *iter2++ / (float) 65535.0;
5425			}
5426		    } else if (type == GL_UNSIGNED_INT) {
5427			if (index_format) {
5428			    widget.ui = *iter2++;
5429			} else {
5430			    widget.ui = (unsigned int) *iter2++ * 65537;
5431			}
5432		    } else {
5433			if (index_format) {
5434			    widget.i = *iter2++;
5435			} else {
5436			    widget.i = ((unsigned int) *iter2++ * 65537)/2;
5437			}
5438		    }
5439		    if (myswap_bytes) {
5440			iter[3] = widget.ub[0];
5441			iter[2] = widget.ub[1];
5442			iter[1] = widget.ub[2];
5443			iter[0] = widget.ub[3];
5444		    } else {
5445			iter[0] = widget.ub[0];
5446			iter[1] = widget.ub[1];
5447			iter[2] = widget.ub[2];
5448			iter[3] = widget.ub[3];
5449		    }
5450		    break;
5451		}
5452		iter += element_size;
5453	    } /* for j */
5454	    start += rowsize;
5455#if 1
5456	    /* want 'iter' pointing at start, not within, row for assertion
5457	     * purposes
5458	     */
5459	    iter= start;
5460#endif
5461	} /* for i */
5462
5463	/* iterators should be one byte past end */
5464	if (!isTypePackedPixel(type)) {
5465	   assert(iter2 == &oldimage[width*height*components]);
5466	}
5467	else {
5468	   assert(iter2 == &oldimage[width*height*
5469				     elements_per_group(format,0)]);
5470	}
5471	assert( iter == &((GLubyte *)userdata)[rowsize*height +
5472					psm->pack_skip_rows * rowsize +
5473					psm->pack_skip_pixels * group_size] );
5474
5475    } /* else */
5476} /* empty_image() */
5477
5478/*--------------------------------------------------------------------------
5479 * Decimation of packed pixel types
5480 *--------------------------------------------------------------------------
5481 */
5482static void extract332(int isSwap,
5483		       const void *packedPixel, GLfloat extractComponents[])
5484{
5485   GLubyte ubyte= *(const GLubyte *)packedPixel;
5486
5487   isSwap= isSwap;		/* turn off warnings */
5488
5489   /* 11100000 == 0xe0 */
5490   /* 00011100 == 0x1c */
5491   /* 00000011 == 0x03 */
5492
5493   extractComponents[0]=   (float)((ubyte & 0xe0)  >> 5) / 7.0;
5494   extractComponents[1]=   (float)((ubyte & 0x1c)  >> 2) / 7.0; /* 7 = 2^3-1 */
5495   extractComponents[2]=   (float)((ubyte & 0x03)      ) / 3.0; /* 3 = 2^2-1 */
5496} /* extract332() */
5497
5498static void shove332(const GLfloat shoveComponents[],
5499		     int index, void *packedPixel)
5500{
5501   /* 11100000 == 0xe0 */
5502   /* 00011100 == 0x1c */
5503   /* 00000011 == 0x03 */
5504
5505   assert(0.0 <= shoveComponents[0] && shoveComponents[0] <= 1.0);
5506   assert(0.0 <= shoveComponents[1] && shoveComponents[1] <= 1.0);
5507   assert(0.0 <= shoveComponents[2] && shoveComponents[2] <= 1.0);
5508
5509   /* due to limited precision, need to round before shoving */
5510   ((GLubyte *)packedPixel)[index]  =
5511     ((GLubyte)((shoveComponents[0] * 7)+0.5)  << 5) & 0xe0;
5512   ((GLubyte *)packedPixel)[index] |=
5513     ((GLubyte)((shoveComponents[1] * 7)+0.5)  << 2) & 0x1c;
5514   ((GLubyte *)packedPixel)[index]  |=
5515     ((GLubyte)((shoveComponents[2] * 3)+0.5)	   ) & 0x03;
5516} /* shove332() */
5517
5518static void extract233rev(int isSwap,
5519			  const void *packedPixel, GLfloat extractComponents[])
5520{
5521   GLubyte ubyte= *(const GLubyte *)packedPixel;
5522
5523   isSwap= isSwap;		/* turn off warnings */
5524
5525   /* 0000,0111 == 0x07 */
5526   /* 0011,1000 == 0x38 */
5527   /* 1100,0000 == 0xC0 */
5528
5529   extractComponents[0]= (float)((ubyte & 0x07)     ) / 7.0;
5530   extractComponents[1]= (float)((ubyte & 0x38) >> 3) / 7.0;
5531   extractComponents[2]= (float)((ubyte & 0xC0) >> 6) / 3.0;
5532} /* extract233rev() */
5533
5534static void shove233rev(const GLfloat shoveComponents[],
5535			int index, void *packedPixel)
5536{
5537   /* 0000,0111 == 0x07 */
5538   /* 0011,1000 == 0x38 */
5539   /* 1100,0000 == 0xC0 */
5540
5541   assert(0.0 <= shoveComponents[0] && shoveComponents[0] <= 1.0);
5542   assert(0.0 <= shoveComponents[1] && shoveComponents[1] <= 1.0);
5543   assert(0.0 <= shoveComponents[2] && shoveComponents[2] <= 1.0);
5544
5545   /* due to limited precision, need to round before shoving */
5546   ((GLubyte *)packedPixel)[index] =
5547     ((GLubyte)((shoveComponents[0] * 7.0)+0.5)     ) & 0x07;
5548   ((GLubyte *)packedPixel)[index]|=
5549     ((GLubyte)((shoveComponents[1] * 7.0)+0.5) << 3) & 0x38;
5550   ((GLubyte *)packedPixel)[index]|=
5551     ((GLubyte)((shoveComponents[2] * 3.0)+0.5) << 6) & 0xC0;
5552} /* shove233rev() */
5553
5554static void extract565(int isSwap,
5555		       const void *packedPixel, GLfloat extractComponents[])
5556{
5557   GLushort ushort;
5558
5559   if (isSwap) {
5560     ushort= __GLU_SWAP_2_BYTES(packedPixel);
5561   }
5562   else {
5563     ushort= *(const GLushort *)packedPixel;
5564   }
5565
5566   /* 11111000,00000000 == 0xf800 */
5567   /* 00000111,11100000 == 0x07e0 */
5568   /* 00000000,00011111 == 0x001f */
5569
5570   extractComponents[0]=(float)((ushort & 0xf800) >> 11) / 31.0;/* 31 = 2^5-1*/
5571   extractComponents[1]=(float)((ushort & 0x07e0) >>  5) / 63.0;/* 63 = 2^6-1*/
5572   extractComponents[2]=(float)((ushort & 0x001f)      ) / 31.0;
5573} /* extract565() */
5574
5575static void shove565(const GLfloat shoveComponents[],
5576		     int index,void *packedPixel)
5577{
5578   /* 11111000,00000000 == 0xf800 */
5579   /* 00000111,11100000 == 0x07e0 */
5580   /* 00000000,00011111 == 0x001f */
5581
5582   assert(0.0 <= shoveComponents[0] && shoveComponents[0] <= 1.0);
5583   assert(0.0 <= shoveComponents[1] && shoveComponents[1] <= 1.0);
5584   assert(0.0 <= shoveComponents[2] && shoveComponents[2] <= 1.0);
5585
5586   /* due to limited precision, need to round before shoving */
5587   ((GLushort *)packedPixel)[index] =
5588     ((GLushort)((shoveComponents[0] * 31)+0.5) << 11) & 0xf800;
5589   ((GLushort *)packedPixel)[index]|=
5590     ((GLushort)((shoveComponents[1] * 63)+0.5) <<  5) & 0x07e0;
5591   ((GLushort *)packedPixel)[index]|=
5592     ((GLushort)((shoveComponents[2] * 31)+0.5)      ) & 0x001f;
5593} /* shove565() */
5594
5595static void extract565rev(int isSwap,
5596			  const void *packedPixel, GLfloat extractComponents[])
5597{
5598   GLushort ushort;
5599
5600   if (isSwap) {
5601     ushort= __GLU_SWAP_2_BYTES(packedPixel);
5602   }
5603   else {
5604     ushort= *(const GLushort *)packedPixel;
5605   }
5606
5607   /* 00000000,00011111 == 0x001f */
5608   /* 00000111,11100000 == 0x07e0 */
5609   /* 11111000,00000000 == 0xf800 */
5610
5611   extractComponents[0]= (float)((ushort & 0x001F)	) / 31.0;
5612   extractComponents[1]= (float)((ushort & 0x07E0) >>  5) / 63.0;
5613   extractComponents[2]= (float)((ushort & 0xF800) >> 11) / 31.0;
5614} /* extract565rev() */
5615
5616static void shove565rev(const GLfloat shoveComponents[],
5617			int index,void *packedPixel)
5618{
5619   /* 00000000,00011111 == 0x001f */
5620   /* 00000111,11100000 == 0x07e0 */
5621   /* 11111000,00000000 == 0xf800 */
5622
5623   assert(0.0 <= shoveComponents[0] && shoveComponents[0] <= 1.0);
5624   assert(0.0 <= shoveComponents[1] && shoveComponents[1] <= 1.0);
5625   assert(0.0 <= shoveComponents[2] && shoveComponents[2] <= 1.0);
5626
5627   /* due to limited precision, need to round before shoving */
5628   ((GLushort *)packedPixel)[index] =
5629     ((GLushort)((shoveComponents[0] * 31.0)+0.5)      ) & 0x001F;
5630   ((GLushort *)packedPixel)[index]|=
5631     ((GLushort)((shoveComponents[1] * 63.0)+0.5) <<  5) & 0x07E0;
5632   ((GLushort *)packedPixel)[index]|=
5633     ((GLushort)((shoveComponents[2] * 31.0)+0.5) << 11) & 0xF800;
5634} /* shove565rev() */
5635
5636static void extract4444(int isSwap,const void *packedPixel,
5637			GLfloat extractComponents[])
5638{
5639   GLushort ushort;
5640
5641   if (isSwap) {
5642     ushort= __GLU_SWAP_2_BYTES(packedPixel);
5643   }
5644   else {
5645     ushort= *(const GLushort *)packedPixel;
5646   }
5647
5648   /* 11110000,00000000 == 0xf000 */
5649   /* 00001111,00000000 == 0x0f00 */
5650   /* 00000000,11110000 == 0x00f0 */
5651   /* 00000000,00001111 == 0x000f */
5652
5653   extractComponents[0]= (float)((ushort & 0xf000) >> 12) / 15.0;/* 15=2^4-1 */
5654   extractComponents[1]= (float)((ushort & 0x0f00) >>  8) / 15.0;
5655   extractComponents[2]= (float)((ushort & 0x00f0) >>  4) / 15.0;
5656   extractComponents[3]= (float)((ushort & 0x000f)	) / 15.0;
5657} /* extract4444() */
5658
5659static void shove4444(const GLfloat shoveComponents[],
5660		      int index,void *packedPixel)
5661{
5662   assert(0.0 <= shoveComponents[0] && shoveComponents[0] <= 1.0);
5663   assert(0.0 <= shoveComponents[1] && shoveComponents[1] <= 1.0);
5664   assert(0.0 <= shoveComponents[2] && shoveComponents[2] <= 1.0);
5665   assert(0.0 <= shoveComponents[3] && shoveComponents[3] <= 1.0);
5666
5667   /* due to limited precision, need to round before shoving */
5668   ((GLushort *)packedPixel)[index] =
5669     ((GLushort)((shoveComponents[0] * 15)+0.5) << 12) & 0xf000;
5670   ((GLushort *)packedPixel)[index]|=
5671     ((GLushort)((shoveComponents[1] * 15)+0.5) <<  8) & 0x0f00;
5672   ((GLushort *)packedPixel)[index]|=
5673     ((GLushort)((shoveComponents[2] * 15)+0.5) <<  4) & 0x00f0;
5674   ((GLushort *)packedPixel)[index]|=
5675     ((GLushort)((shoveComponents[3] * 15)+0.5)      ) & 0x000f;
5676} /* shove4444() */
5677
5678static void extract4444rev(int isSwap,const void *packedPixel,
5679			   GLfloat extractComponents[])
5680{
5681   GLushort ushort;
5682
5683   if (isSwap) {
5684     ushort= __GLU_SWAP_2_BYTES(packedPixel);
5685   }
5686   else {
5687     ushort= *(const GLushort *)packedPixel;
5688   }
5689
5690   /* 00000000,00001111 == 0x000f */
5691   /* 00000000,11110000 == 0x00f0 */
5692   /* 00001111,00000000 == 0x0f00 */
5693   /* 11110000,00000000 == 0xf000 */
5694
5695   /* 15 = 2^4-1 */
5696   extractComponents[0]= (float)((ushort & 0x000F)	) / 15.0;
5697   extractComponents[1]= (float)((ushort & 0x00F0) >>  4) / 15.0;
5698   extractComponents[2]= (float)((ushort & 0x0F00) >>  8) / 15.0;
5699   extractComponents[3]= (float)((ushort & 0xF000) >> 12) / 15.0;
5700} /* extract4444rev() */
5701
5702static void shove4444rev(const GLfloat shoveComponents[],
5703			 int index,void *packedPixel)
5704{
5705   /* 00000000,00001111 == 0x000f */
5706   /* 00000000,11110000 == 0x00f0 */
5707   /* 00001111,00000000 == 0x0f00 */
5708   /* 11110000,00000000 == 0xf000 */
5709
5710   assert(0.0 <= shoveComponents[0] && shoveComponents[0] <= 1.0);
5711   assert(0.0 <= shoveComponents[1] && shoveComponents[1] <= 1.0);
5712   assert(0.0 <= shoveComponents[2] && shoveComponents[2] <= 1.0);
5713   assert(0.0 <= shoveComponents[3] && shoveComponents[3] <= 1.0);
5714
5715   /* due to limited precision, need to round before shoving */
5716   ((GLushort *)packedPixel)[index] =
5717     ((GLushort)((shoveComponents[0] * 15)+0.5)      ) & 0x000F;
5718   ((GLushort *)packedPixel)[index]|=
5719     ((GLushort)((shoveComponents[1] * 15)+0.5) <<  4) & 0x00F0;
5720   ((GLushort *)packedPixel)[index]|=
5721     ((GLushort)((shoveComponents[2] * 15)+0.5) <<  8) & 0x0F00;
5722   ((GLushort *)packedPixel)[index]|=
5723     ((GLushort)((shoveComponents[3] * 15)+0.5) << 12) & 0xF000;
5724} /* shove4444rev() */
5725
5726static void extract5551(int isSwap,const void *packedPixel,
5727			GLfloat extractComponents[])
5728{
5729   GLushort ushort;
5730
5731   if (isSwap) {
5732     ushort= __GLU_SWAP_2_BYTES(packedPixel);
5733   }
5734   else {
5735     ushort= *(const GLushort *)packedPixel;
5736   }
5737
5738   /* 11111000,00000000 == 0xf800 */
5739   /* 00000111,11000000 == 0x07c0 */
5740   /* 00000000,00111110 == 0x003e */
5741   /* 00000000,00000001 == 0x0001 */
5742
5743   extractComponents[0]=(float)((ushort & 0xf800) >> 11) / 31.0;/* 31 = 2^5-1*/
5744   extractComponents[1]=(float)((ushort & 0x07c0) >>  6) / 31.0;
5745   extractComponents[2]=(float)((ushort & 0x003e) >>  1) / 31.0;
5746   extractComponents[3]=(float)((ushort & 0x0001)      );
5747} /* extract5551() */
5748
5749static void shove5551(const GLfloat shoveComponents[],
5750		      int index,void *packedPixel)
5751{
5752   /* 11111000,00000000 == 0xf800 */
5753   /* 00000111,11000000 == 0x07c0 */
5754   /* 00000000,00111110 == 0x003e */
5755   /* 00000000,00000001 == 0x0001 */
5756
5757   assert(0.0 <= shoveComponents[0] && shoveComponents[0] <= 1.0);
5758   assert(0.0 <= shoveComponents[1] && shoveComponents[1] <= 1.0);
5759   assert(0.0 <= shoveComponents[2] && shoveComponents[2] <= 1.0);
5760   assert(0.0 <= shoveComponents[3] && shoveComponents[3] <= 1.0);
5761
5762   /* due to limited precision, need to round before shoving */
5763   ((GLushort *)packedPixel)[index]  =
5764     ((GLushort)((shoveComponents[0] * 31)+0.5) << 11) & 0xf800;
5765   ((GLushort *)packedPixel)[index]|=
5766     ((GLushort)((shoveComponents[1] * 31)+0.5) <<  6) & 0x07c0;
5767   ((GLushort *)packedPixel)[index]|=
5768     ((GLushort)((shoveComponents[2] * 31)+0.5) <<  1) & 0x003e;
5769   ((GLushort *)packedPixel)[index]|=
5770     ((GLushort)((shoveComponents[3])+0.5)	     ) & 0x0001;
5771} /* shove5551() */
5772
5773static void extract1555rev(int isSwap,const void *packedPixel,
5774			   GLfloat extractComponents[])
5775{
5776   GLushort ushort;
5777
5778   if (isSwap) {
5779     ushort= __GLU_SWAP_2_BYTES(packedPixel);
5780   }
5781   else {
5782     ushort= *(const GLushort *)packedPixel;
5783   }
5784
5785   /* 00000000,00011111 == 0x001F */
5786   /* 00000011,11100000 == 0x03E0 */
5787   /* 01111100,00000000 == 0x7C00 */
5788   /* 10000000,00000000 == 0x8000 */
5789
5790   /* 31 = 2^5-1 */
5791   extractComponents[0]= (float)((ushort & 0x001F)	) / 31.0;
5792   extractComponents[1]= (float)((ushort & 0x03E0) >>  5) / 31.0;
5793   extractComponents[2]= (float)((ushort & 0x7C00) >> 10) / 31.0;
5794   extractComponents[3]= (float)((ushort & 0x8000) >> 15);
5795} /* extract1555rev() */
5796
5797static void shove1555rev(const GLfloat shoveComponents[],
5798			 int index,void *packedPixel)
5799{
5800   /* 00000000,00011111 == 0x001F */
5801   /* 00000011,11100000 == 0x03E0 */
5802   /* 01111100,00000000 == 0x7C00 */
5803   /* 10000000,00000000 == 0x8000 */
5804
5805   assert(0.0 <= shoveComponents[0] && shoveComponents[0] <= 1.0);
5806   assert(0.0 <= shoveComponents[1] && shoveComponents[1] <= 1.0);
5807   assert(0.0 <= shoveComponents[2] && shoveComponents[2] <= 1.0);
5808   assert(0.0 <= shoveComponents[3] && shoveComponents[3] <= 1.0);
5809
5810   /* due to limited precision, need to round before shoving */
5811   ((GLushort *)packedPixel)[index] =
5812     ((GLushort)((shoveComponents[0] * 31)+0.5)      ) & 0x001F;
5813   ((GLushort *)packedPixel)[index]|=
5814     ((GLushort)((shoveComponents[1] * 31)+0.5) <<  5) & 0x03E0;
5815   ((GLushort *)packedPixel)[index]|=
5816     ((GLushort)((shoveComponents[2] * 31)+0.5) << 10) & 0x7C00;
5817   ((GLushort *)packedPixel)[index]|=
5818     ((GLushort)((shoveComponents[3])+0.5)	<< 15) & 0x8000;
5819} /* shove1555rev() */
5820
5821static void extract8888(int isSwap,
5822			const void *packedPixel, GLfloat extractComponents[])
5823{
5824   GLuint uint;
5825
5826   if (isSwap) {
5827     uint= __GLU_SWAP_4_BYTES(packedPixel);
5828   }
5829   else {
5830     uint= *(const GLuint *)packedPixel;
5831   }
5832
5833   /* 11111111,00000000,00000000,00000000 == 0xff000000 */
5834   /* 00000000,11111111,00000000,00000000 == 0x00ff0000 */
5835   /* 00000000,00000000,11111111,00000000 == 0x0000ff00 */
5836   /* 00000000,00000000,00000000,11111111 == 0x000000ff */
5837
5838   /* 255 = 2^8-1 */
5839   extractComponents[0]= (float)((uint & 0xff000000) >> 24) / 255.0;
5840   extractComponents[1]= (float)((uint & 0x00ff0000) >> 16) / 255.0;
5841   extractComponents[2]= (float)((uint & 0x0000ff00) >>  8) / 255.0;
5842   extractComponents[3]= (float)((uint & 0x000000ff)	  ) / 255.0;
5843} /* extract8888() */
5844
5845static void shove8888(const GLfloat shoveComponents[],
5846		      int index,void *packedPixel)
5847{
5848   /* 11111111,00000000,00000000,00000000 == 0xff000000 */
5849   /* 00000000,11111111,00000000,00000000 == 0x00ff0000 */
5850   /* 00000000,00000000,11111111,00000000 == 0x0000ff00 */
5851   /* 00000000,00000000,00000000,11111111 == 0x000000ff */
5852
5853   assert(0.0 <= shoveComponents[0] && shoveComponents[0] <= 1.0);
5854   assert(0.0 <= shoveComponents[1] && shoveComponents[1] <= 1.0);
5855   assert(0.0 <= shoveComponents[2] && shoveComponents[2] <= 1.0);
5856   assert(0.0 <= shoveComponents[3] && shoveComponents[3] <= 1.0);
5857
5858   /* due to limited precision, need to round before shoving */
5859   ((GLuint *)packedPixel)[index] =
5860     ((GLuint)((shoveComponents[0] * 255)+0.5) << 24) & 0xff000000;
5861   ((GLuint *)packedPixel)[index]|=
5862     ((GLuint)((shoveComponents[1] * 255)+0.5) << 16) & 0x00ff0000;
5863   ((GLuint *)packedPixel)[index]|=
5864     ((GLuint)((shoveComponents[2] * 255)+0.5) <<  8) & 0x0000ff00;
5865   ((GLuint *)packedPixel)[index]|=
5866     ((GLuint)((shoveComponents[3] * 255)+0.5)	    ) & 0x000000ff;
5867} /* shove8888() */
5868
5869static void extract8888rev(int isSwap,
5870			   const void *packedPixel,GLfloat extractComponents[])
5871{
5872   GLuint uint;
5873
5874   if (isSwap) {
5875     uint= __GLU_SWAP_4_BYTES(packedPixel);
5876   }
5877   else {
5878     uint= *(const GLuint *)packedPixel;
5879   }
5880
5881   /* 00000000,00000000,00000000,11111111 == 0x000000ff */
5882   /* 00000000,00000000,11111111,00000000 == 0x0000ff00 */
5883   /* 00000000,11111111,00000000,00000000 == 0x00ff0000 */
5884   /* 11111111,00000000,00000000,00000000 == 0xff000000 */
5885
5886   /* 255 = 2^8-1 */
5887   extractComponents[0]= (float)((uint & 0x000000FF)	  ) / 255.0;
5888   extractComponents[1]= (float)((uint & 0x0000FF00) >>  8) / 255.0;
5889   extractComponents[2]= (float)((uint & 0x00FF0000) >> 16) / 255.0;
5890   extractComponents[3]= (float)((uint & 0xFF000000) >> 24) / 255.0;
5891} /* extract8888rev() */
5892
5893static void shove8888rev(const GLfloat shoveComponents[],
5894			 int index,void *packedPixel)
5895{
5896   /* 00000000,00000000,00000000,11111111 == 0x000000ff */
5897   /* 00000000,00000000,11111111,00000000 == 0x0000ff00 */
5898   /* 00000000,11111111,00000000,00000000 == 0x00ff0000 */
5899   /* 11111111,00000000,00000000,00000000 == 0xff000000 */
5900
5901   assert(0.0 <= shoveComponents[0] && shoveComponents[0] <= 1.0);
5902   assert(0.0 <= shoveComponents[1] && shoveComponents[1] <= 1.0);
5903   assert(0.0 <= shoveComponents[2] && shoveComponents[2] <= 1.0);
5904   assert(0.0 <= shoveComponents[3] && shoveComponents[3] <= 1.0);
5905
5906   /* due to limited precision, need to round before shoving */
5907   ((GLuint *)packedPixel)[index] =
5908     ((GLuint)((shoveComponents[0] * 255)+0.5)	    ) & 0x000000FF;
5909   ((GLuint *)packedPixel)[index]|=
5910     ((GLuint)((shoveComponents[1] * 255)+0.5) <<  8) & 0x0000FF00;
5911   ((GLuint *)packedPixel)[index]|=
5912     ((GLuint)((shoveComponents[2] * 255)+0.5) << 16) & 0x00FF0000;
5913   ((GLuint *)packedPixel)[index]|=
5914     ((GLuint)((shoveComponents[3] * 255)+0.5) << 24) & 0xFF000000;
5915} /* shove8888rev() */
5916
5917static void extract1010102(int isSwap,
5918			   const void *packedPixel,GLfloat extractComponents[])
5919{
5920   GLuint uint;
5921
5922   if (isSwap) {
5923     uint= __GLU_SWAP_4_BYTES(packedPixel);
5924   }
5925   else {
5926     uint= *(const GLuint *)packedPixel;
5927   }
5928
5929   /* 11111111,11000000,00000000,00000000 == 0xffc00000 */
5930   /* 00000000,00111111,11110000,00000000 == 0x003ff000 */
5931   /* 00000000,00000000,00001111,11111100 == 0x00000ffc */
5932   /* 00000000,00000000,00000000,00000011 == 0x00000003 */
5933
5934   /* 1023 = 2^10-1 */
5935   extractComponents[0]= (float)((uint & 0xffc00000) >> 22) / 1023.0;
5936   extractComponents[1]= (float)((uint & 0x003ff000) >> 12) / 1023.0;
5937   extractComponents[2]= (float)((uint & 0x00000ffc) >>  2) / 1023.0;
5938   extractComponents[3]= (float)((uint & 0x00000003)	  ) / 3.0;
5939} /* extract1010102() */
5940
5941static void shove1010102(const GLfloat shoveComponents[],
5942			 int index,void *packedPixel)
5943{
5944   /* 11111111,11000000,00000000,00000000 == 0xffc00000 */
5945   /* 00000000,00111111,11110000,00000000 == 0x003ff000 */
5946   /* 00000000,00000000,00001111,11111100 == 0x00000ffc */
5947   /* 00000000,00000000,00000000,00000011 == 0x00000003 */
5948
5949   assert(0.0 <= shoveComponents[0] && shoveComponents[0] <= 1.0);
5950   assert(0.0 <= shoveComponents[1] && shoveComponents[1] <= 1.0);
5951   assert(0.0 <= shoveComponents[2] && shoveComponents[2] <= 1.0);
5952   assert(0.0 <= shoveComponents[3] && shoveComponents[3] <= 1.0);
5953
5954   /* due to limited precision, need to round before shoving */
5955   ((GLuint *)packedPixel)[index] =
5956     ((GLuint)((shoveComponents[0] * 1023)+0.5) << 22) & 0xffc00000;
5957   ((GLuint *)packedPixel)[index]|=
5958     ((GLuint)((shoveComponents[1] * 1023)+0.5) << 12) & 0x003ff000;
5959   ((GLuint *)packedPixel)[index]|=
5960     ((GLuint)((shoveComponents[2] * 1023)+0.5) <<  2) & 0x00000ffc;
5961   ((GLuint *)packedPixel)[index]|=
5962     ((GLuint)((shoveComponents[3] * 3)+0.5)	     ) & 0x00000003;
5963} /* shove1010102() */
5964
5965static void extract2101010rev(int isSwap,
5966			      const void *packedPixel,
5967			      GLfloat extractComponents[])
5968{
5969   GLuint uint;
5970
5971   if (isSwap) {
5972     uint= __GLU_SWAP_4_BYTES(packedPixel);
5973   }
5974   else {
5975     uint= *(const GLuint *)packedPixel;
5976   }
5977
5978   /* 00000000,00000000,00000011,11111111 == 0x000003FF */
5979   /* 00000000,00001111,11111100,00000000 == 0x000FFC00 */
5980   /* 00111111,11110000,00000000,00000000 == 0x3FF00000 */
5981   /* 11000000,00000000,00000000,00000000 == 0xC0000000 */
5982
5983   /* 1023 = 2^10-1 */
5984   extractComponents[0]= (float)((uint & 0x000003FF)	  ) / 1023.0;
5985   extractComponents[1]= (float)((uint & 0x000FFC00) >> 10) / 1023.0;
5986   extractComponents[2]= (float)((uint & 0x3FF00000) >> 20) / 1023.0;
5987   extractComponents[3]= (float)((uint & 0xC0000000) >> 30) / 3.0;
5988   /* 3 = 2^2-1 */
5989} /* extract2101010rev() */
5990
5991static void shove2101010rev(const GLfloat shoveComponents[],
5992			    int index,void *packedPixel)
5993{
5994   /* 00000000,00000000,00000011,11111111 == 0x000003FF */
5995   /* 00000000,00001111,11111100,00000000 == 0x000FFC00 */
5996   /* 00111111,11110000,00000000,00000000 == 0x3FF00000 */
5997   /* 11000000,00000000,00000000,00000000 == 0xC0000000 */
5998
5999   assert(0.0 <= shoveComponents[0] && shoveComponents[0] <= 1.0);
6000   assert(0.0 <= shoveComponents[1] && shoveComponents[1] <= 1.0);
6001   assert(0.0 <= shoveComponents[2] && shoveComponents[2] <= 1.0);
6002   assert(0.0 <= shoveComponents[3] && shoveComponents[3] <= 1.0);
6003
6004   /* due to limited precision, need to round before shoving */
6005   ((GLuint *)packedPixel)[index] =
6006     ((GLuint)((shoveComponents[0] * 1023)+0.5)      ) & 0x000003FF;
6007   ((GLuint *)packedPixel)[index]|=
6008     ((GLuint)((shoveComponents[1] * 1023)+0.5) << 10) & 0x000FFC00;
6009   ((GLuint *)packedPixel)[index]|=
6010     ((GLuint)((shoveComponents[2] * 1023)+0.5) << 20) & 0x3FF00000;
6011   ((GLuint *)packedPixel)[index]|=
6012     ((GLuint)((shoveComponents[3] * 3)+0.5)	<< 30) & 0xC0000000;
6013} /* shove2101010rev() */
6014
6015static void scaleInternalPackedPixel(int components,
6016				     void (*extractPackedPixel)
6017				     (int, const void *,GLfloat []),
6018				     void (*shovePackedPixel)
6019				     (const GLfloat [], int, void *),
6020				     GLint widthIn,GLint heightIn,
6021				     const void *dataIn,
6022				     GLint widthOut,GLint heightOut,
6023				     void *dataOut,
6024				     GLint pixelSizeInBytes,
6025				     GLint rowSizeInBytes,GLint isSwap)
6026{
6027    float convx;
6028    float convy;
6029    float percent;
6030
6031    /* Max components in a format is 4, so... */
6032    float totals[4];
6033    float extractTotals[4], extractMoreTotals[4], shoveTotals[4];
6034
6035    float area;
6036    int i,j,k,xindex;
6037
6038    const char *temp, *temp0;
6039    int outindex;
6040
6041    int lowx_int, highx_int, lowy_int, highy_int;
6042    float x_percent, y_percent;
6043    float lowx_float, highx_float, lowy_float, highy_float;
6044    float convy_float, convx_float;
6045    int convy_int, convx_int;
6046    int l, m;
6047    const char *left, *right;
6048
6049    if (widthIn == widthOut*2 && heightIn == heightOut*2) {
6050	halveImagePackedPixel(components,extractPackedPixel,shovePackedPixel,
6051			      widthIn, heightIn, dataIn, dataOut,
6052			      pixelSizeInBytes,rowSizeInBytes,isSwap);
6053	return;
6054    }
6055    convy = (float) heightIn/heightOut;
6056    convx = (float) widthIn/widthOut;
6057    convy_int = floor(convy);
6058    convy_float = convy - convy_int;
6059    convx_int = floor(convx);
6060    convx_float = convx - convx_int;
6061
6062    area = convx * convy;
6063
6064    lowy_int = 0;
6065    lowy_float = 0;
6066    highy_int = convy_int;
6067    highy_float = convy_float;
6068
6069    for (i = 0; i < heightOut; i++) {
6070	lowx_int = 0;
6071	lowx_float = 0;
6072	highx_int = convx_int;
6073	highx_float = convx_float;
6074
6075	for (j = 0; j < widthOut; j++) {
6076	    /*
6077	    ** Ok, now apply box filter to box that goes from (lowx, lowy)
6078	    ** to (highx, highy) on input data into this pixel on output
6079	    ** data.
6080	    */
6081	    totals[0] = totals[1] = totals[2] = totals[3] = 0.0;
6082
6083	    /* calculate the value for pixels in the 1st row */
6084	    xindex = lowx_int*pixelSizeInBytes;
6085	    if((highy_int>lowy_int) && (highx_int>lowx_int)) {
6086
6087		y_percent = 1-lowy_float;
6088		temp = (const char *)dataIn + xindex + lowy_int * rowSizeInBytes;
6089		percent = y_percent * (1-lowx_float);
6090#if 0
6091		for (k = 0, temp_index = temp; k < components;
6092		     k++, temp_index += element_size) {
6093		    if (myswap_bytes) {
6094			totals[k] += __GLU_SWAP_2_BYTES(temp_index) * percent;
6095		    } else {
6096			totals[k] += *(const GLushort*)temp_index * percent;
6097		    }
6098		}
6099#else
6100		(*extractPackedPixel)(isSwap,temp,extractTotals);
6101		for (k = 0; k < components; k++) {
6102		   totals[k]+= extractTotals[k] * percent;
6103		}
6104#endif
6105		left = temp;
6106		for(l = lowx_int+1; l < highx_int; l++) {
6107		    temp += pixelSizeInBytes;
6108#if 0
6109		    for (k = 0, temp_index = temp; k < components;
6110			 k++, temp_index += element_size) {
6111			if (myswap_bytes) {
6112			    totals[k] +=
6113				 __GLU_SWAP_2_BYTES(temp_index) * y_percent;
6114			} else {
6115			    totals[k] += *(const GLushort*)temp_index * y_percent;
6116			}
6117		    }
6118#else
6119		    (*extractPackedPixel)(isSwap,temp,extractTotals);
6120		    for (k = 0; k < components; k++) {
6121		       totals[k]+= extractTotals[k] * y_percent;
6122		    }
6123#endif
6124		}
6125		temp += pixelSizeInBytes;
6126		right = temp;
6127		percent = y_percent * highx_float;
6128#if 0
6129		for (k = 0, temp_index = temp; k < components;
6130		     k++, temp_index += element_size) {
6131		    if (myswap_bytes) {
6132			totals[k] += __GLU_SWAP_2_BYTES(temp_index) * percent;
6133		    } else {
6134			totals[k] += *(const GLushort*)temp_index * percent;
6135		    }
6136		}
6137#else
6138		(*extractPackedPixel)(isSwap,temp,extractTotals);
6139		for (k = 0; k < components; k++) {
6140		   totals[k]+= extractTotals[k] * percent;
6141		}
6142#endif
6143
6144		/* calculate the value for pixels in the last row */
6145
6146		y_percent = highy_float;
6147		percent = y_percent * (1-lowx_float);
6148		temp = (const char *)dataIn + xindex + highy_int * rowSizeInBytes;
6149#if 0
6150		for (k = 0, temp_index = temp; k < components;
6151		     k++, temp_index += element_size) {
6152		    if (myswap_bytes) {
6153			totals[k] += __GLU_SWAP_2_BYTES(temp_index) * percent;
6154		    } else {
6155			totals[k] += *(const GLushort*)temp_index * percent;
6156		    }
6157		}
6158#else
6159		(*extractPackedPixel)(isSwap,temp,extractTotals);
6160		for (k = 0; k < components; k++) {
6161		   totals[k]+= extractTotals[k] * percent;
6162		}
6163#endif
6164		for(l = lowx_int+1; l < highx_int; l++) {
6165		    temp += pixelSizeInBytes;
6166#if 0
6167		    for (k = 0, temp_index = temp; k < components;
6168			 k++, temp_index += element_size) {
6169			if (myswap_bytes) {
6170			    totals[k] +=
6171				 __GLU_SWAP_2_BYTES(temp_index) * y_percent;
6172			} else {
6173			    totals[k] += *(const GLushort*)temp_index * y_percent;
6174			}
6175		    }
6176#else
6177		    (*extractPackedPixel)(isSwap,temp,extractTotals);
6178		    for (k = 0; k < components; k++) {
6179		       totals[k]+= extractTotals[k] * y_percent;
6180		    }
6181#endif
6182
6183		}
6184		temp += pixelSizeInBytes;
6185		percent = y_percent * highx_float;
6186#if 0
6187		for (k = 0, temp_index = temp; k < components;
6188		     k++, temp_index += element_size) {
6189		    if (myswap_bytes) {
6190			totals[k] += __GLU_SWAP_2_BYTES(temp_index) * percent;
6191		    } else {
6192			totals[k] += *(const GLushort*)temp_index * percent;
6193		    }
6194		}
6195#else
6196		(*extractPackedPixel)(isSwap,temp,extractTotals);
6197		for (k = 0; k < components; k++) {
6198		   totals[k]+= extractTotals[k] * percent;
6199		}
6200#endif
6201
6202		/* calculate the value for pixels in the 1st and last column */
6203		for(m = lowy_int+1; m < highy_int; m++) {
6204		    left += rowSizeInBytes;
6205		    right += rowSizeInBytes;
6206#if 0
6207		    for (k = 0; k < components;
6208			 k++, left += element_size, right += element_size) {
6209			if (myswap_bytes) {
6210			    totals[k] +=
6211				__GLU_SWAP_2_BYTES(left) * (1-lowx_float) +
6212				__GLU_SWAP_2_BYTES(right) * highx_float;
6213			} else {
6214			    totals[k] += *(const GLushort*)left * (1-lowx_float)
6215				       + *(const GLushort*)right * highx_float;
6216			}
6217		    }
6218#else
6219		    (*extractPackedPixel)(isSwap,left,extractTotals);
6220		    (*extractPackedPixel)(isSwap,right,extractMoreTotals);
6221		    for (k = 0; k < components; k++) {
6222		       totals[k]+= (extractTotals[k]*(1-lowx_float) +
6223				   extractMoreTotals[k]*highx_float);
6224		    }
6225#endif
6226		}
6227	    } else if (highy_int > lowy_int) {
6228		x_percent = highx_float - lowx_float;
6229		percent = (1-lowy_float)*x_percent;
6230		temp = (const char *)dataIn + xindex + lowy_int*rowSizeInBytes;
6231#if 0
6232		for (k = 0, temp_index = temp; k < components;
6233		     k++, temp_index += element_size) {
6234		    if (myswap_bytes) {
6235			totals[k] += __GLU_SWAP_2_BYTES(temp_index) * percent;
6236		    } else {
6237			totals[k] += *(const GLushort*)temp_index * percent;
6238		    }
6239		}
6240#else
6241		(*extractPackedPixel)(isSwap,temp,extractTotals);
6242		for (k = 0; k < components; k++) {
6243		   totals[k]+= extractTotals[k] * percent;
6244		}
6245#endif
6246		for(m = lowy_int+1; m < highy_int; m++) {
6247		    temp += rowSizeInBytes;
6248#if 0
6249		    for (k = 0, temp_index = temp; k < components;
6250			 k++, temp_index += element_size) {
6251			if (myswap_bytes) {
6252			    totals[k] +=
6253				__GLU_SWAP_2_BYTES(temp_index) * x_percent;
6254			} else {
6255			    totals[k] += *(const GLushort*)temp_index * x_percent;
6256			}
6257		    }
6258#else
6259		    (*extractPackedPixel)(isSwap,temp,extractTotals);
6260		    for (k = 0; k < components; k++) {
6261		       totals[k]+= extractTotals[k] * x_percent;
6262		    }
6263#endif
6264		}
6265		percent = x_percent * highy_float;
6266		temp += rowSizeInBytes;
6267#if 0
6268		for (k = 0, temp_index = temp; k < components;
6269		     k++, temp_index += element_size) {
6270		    if (myswap_bytes) {
6271			totals[k] += __GLU_SWAP_2_BYTES(temp_index) * percent;
6272		    } else {
6273			totals[k] += *(const GLushort*)temp_index * percent;
6274		    }
6275		}
6276#else
6277		(*extractPackedPixel)(isSwap,temp,extractTotals);
6278		for (k = 0; k < components; k++) {
6279		   totals[k]+= extractTotals[k] * percent;
6280		}
6281#endif
6282	    } else if (highx_int > lowx_int) {
6283		y_percent = highy_float - lowy_float;
6284		percent = (1-lowx_float)*y_percent;
6285		temp = (const char *)dataIn + xindex + lowy_int*rowSizeInBytes;
6286#if 0
6287		for (k = 0, temp_index = temp; k < components;
6288		     k++, temp_index += element_size) {
6289		    if (myswap_bytes) {
6290			totals[k] += __GLU_SWAP_2_BYTES(temp_index) * percent;
6291		    } else {
6292			totals[k] += *(const GLushort*)temp_index * percent;
6293		    }
6294		}
6295#else
6296		(*extractPackedPixel)(isSwap,temp,extractTotals);
6297		for (k = 0; k < components; k++) {
6298		   totals[k]+= extractTotals[k] * percent;
6299		}
6300#endif
6301		for (l = lowx_int+1; l < highx_int; l++) {
6302		    temp += pixelSizeInBytes;
6303#if 0
6304		    for (k = 0, temp_index = temp; k < components;
6305			 k++, temp_index += element_size) {
6306			if (myswap_bytes) {
6307			    totals[k] +=
6308				__GLU_SWAP_2_BYTES(temp_index) * y_percent;
6309			} else {
6310			    totals[k] += *(const GLushort*)temp_index * y_percent;
6311			}
6312		    }
6313#else
6314		(*extractPackedPixel)(isSwap,temp,extractTotals);
6315		for (k = 0; k < components; k++) {
6316		   totals[k]+= extractTotals[k] * y_percent;
6317		}
6318#endif
6319		}
6320		temp += pixelSizeInBytes;
6321		percent = y_percent * highx_float;
6322#if 0
6323		for (k = 0, temp_index = temp; k < components;
6324		     k++, temp_index += element_size) {
6325		    if (myswap_bytes) {
6326			totals[k] += __GLU_SWAP_2_BYTES(temp_index) * percent;
6327		    } else {
6328			totals[k] += *(const GLushort*)temp_index * percent;
6329		    }
6330		}
6331#else
6332		(*extractPackedPixel)(isSwap,temp,extractTotals);
6333		for (k = 0; k < components; k++) {
6334		   totals[k]+= extractTotals[k] * percent;
6335		}
6336#endif
6337	    } else {
6338		percent = (highy_float-lowy_float)*(highx_float-lowx_float);
6339		temp = (const char *)dataIn + xindex + lowy_int * rowSizeInBytes;
6340#if 0
6341		for (k = 0, temp_index = temp; k < components;
6342		     k++, temp_index += element_size) {
6343		    if (myswap_bytes) {
6344			totals[k] += __GLU_SWAP_2_BYTES(temp_index) * percent;
6345		    } else {
6346			totals[k] += *(const GLushort*)temp_index * percent;
6347		    }
6348		}
6349#else
6350		(*extractPackedPixel)(isSwap,temp,extractTotals);
6351		for (k = 0; k < components; k++) {
6352		   totals[k]+= extractTotals[k] * percent;
6353		}
6354#endif
6355	    }
6356
6357	    /* this is for the pixels in the body */
6358	    temp0 = (const char *)dataIn + xindex + pixelSizeInBytes + (lowy_int+1)*rowSizeInBytes;
6359	    for (m = lowy_int+1; m < highy_int; m++) {
6360		temp = temp0;
6361		for(l = lowx_int+1; l < highx_int; l++) {
6362#if 0
6363		    for (k = 0, temp_index = temp; k < components;
6364			 k++, temp_index += element_size) {
6365			if (myswap_bytes) {
6366			    totals[k] += __GLU_SWAP_2_BYTES(temp_index);
6367			} else {
6368			    totals[k] += *(const GLushort*)temp_index;
6369			}
6370		    }
6371#else
6372		    (*extractPackedPixel)(isSwap,temp,extractTotals);
6373		    for (k = 0; k < components; k++) {
6374		       totals[k]+= extractTotals[k];
6375		    }
6376#endif
6377		    temp += pixelSizeInBytes;
6378		}
6379		temp0 += rowSizeInBytes;
6380	    }
6381
6382	    outindex = (j + (i * widthOut)); /* * (components == 1) */
6383#if 0
6384	    for (k = 0; k < components; k++) {
6385		dataout[outindex + k] = totals[k]/area;
6386		/*printf("totals[%d] = %f\n", k, totals[k]);*/
6387	    }
6388#else
6389	    for (k = 0; k < components; k++) {
6390		shoveTotals[k]= totals[k]/area;
6391	    }
6392	    (*shovePackedPixel)(shoveTotals,outindex,(void *)dataOut);
6393#endif
6394	    lowx_int = highx_int;
6395	    lowx_float = highx_float;
6396	    highx_int += convx_int;
6397	    highx_float += convx_float;
6398	    if(highx_float > 1) {
6399		highx_float -= 1.0;
6400		highx_int++;
6401	    }
6402	}
6403	lowy_int = highy_int;
6404	lowy_float = highy_float;
6405	highy_int += convy_int;
6406	highy_float += convy_float;
6407	if(highy_float > 1) {
6408	    highy_float -= 1.0;
6409	    highy_int++;
6410	}
6411    }
6412
6413    assert(outindex == (widthOut*heightOut - 1));
6414} /* scaleInternalPackedPixel() */
6415
6416/* rowSizeInBytes is at least the width (in bytes) due to padding on
6417 *  inputs; not always equal. Output NEVER has row padding.
6418 */
6419static void halveImagePackedPixel(int components,
6420				  void (*extractPackedPixel)
6421				  (int, const void *,GLfloat []),
6422				  void (*shovePackedPixel)
6423				  (const GLfloat [],int, void *),
6424				  GLint width, GLint height,
6425				  const void *dataIn, void *dataOut,
6426				  GLint pixelSizeInBytes,
6427				  GLint rowSizeInBytes, GLint isSwap)
6428{
6429   /* handle case where there is only 1 column/row */
6430   if (width == 1 || height == 1) {
6431      assert(!(width == 1 && height == 1)); /* can't be 1x1 */
6432      halve1DimagePackedPixel(components,extractPackedPixel,shovePackedPixel,
6433			      width,height,dataIn,dataOut,pixelSizeInBytes,
6434			      rowSizeInBytes,isSwap);
6435      return;
6436   }
6437
6438   {
6439      int ii, jj;
6440
6441      int halfWidth= width / 2;
6442      int halfHeight= height / 2;
6443      const char *src= (const char *) dataIn;
6444      int padBytes= rowSizeInBytes - (width*pixelSizeInBytes);
6445      int outIndex= 0;
6446
6447      for (ii= 0; ii< halfHeight; ii++) {
6448	 for (jj= 0; jj< halfWidth; jj++) {
6449#define BOX4 4
6450	    float totals[4];	/* 4 is maximum components */
6451	    float extractTotals[BOX4][4]; /* 4 is maximum components */
6452	    int cc;
6453
6454	    (*extractPackedPixel)(isSwap,src,
6455				  &extractTotals[0][0]);
6456	    (*extractPackedPixel)(isSwap,(src+pixelSizeInBytes),
6457				  &extractTotals[1][0]);
6458	    (*extractPackedPixel)(isSwap,(src+rowSizeInBytes),
6459				  &extractTotals[2][0]);
6460	    (*extractPackedPixel)(isSwap,
6461				  (src+rowSizeInBytes+pixelSizeInBytes),
6462				  &extractTotals[3][0]);
6463	    for (cc = 0; cc < components; cc++) {
6464	       int kk;
6465
6466	       /* grab 4 pixels to average */
6467	       totals[cc]= 0.0;
6468	       /* totals[RED]= extractTotals[0][RED]+extractTotals[1][RED]+
6469		*	       extractTotals[2][RED]+extractTotals[3][RED];
6470		* totals[RED]/= 4.0;
6471		*/
6472	       for (kk = 0; kk < BOX4; kk++) {
6473		  totals[cc]+= extractTotals[kk][cc];
6474	       }
6475	       totals[cc]/= (float)BOX4;
6476	    }
6477	    (*shovePackedPixel)(totals,outIndex,dataOut);
6478
6479	    outIndex++;
6480	    /* skip over to next square of 4 */
6481	    src+= pixelSizeInBytes + pixelSizeInBytes;
6482	 }
6483	 /* skip past pad bytes, if any, to get to next row */
6484	 src+= padBytes;
6485
6486	 /* src is at beginning of a row here, but it's the second row of
6487	  * the square block of 4 pixels that we just worked on so we
6488	  * need to go one more row.
6489	  * i.e.,
6490	  *		      OO...
6491	  *	      here -->OO...
6492	  *	  but want -->OO...
6493	  *		      OO...
6494	  *		      ...
6495	  */
6496	 src+= rowSizeInBytes;
6497      }
6498
6499      /* both pointers must reach one byte after the end */
6500      assert(src == &((const char *)dataIn)[rowSizeInBytes*height]);
6501      assert(outIndex == halfWidth * halfHeight);
6502   }
6503} /* halveImagePackedPixel() */
6504
6505static void halve1DimagePackedPixel(int components,
6506				    void (*extractPackedPixel)
6507				    (int, const void *,GLfloat []),
6508				    void (*shovePackedPixel)
6509				    (const GLfloat [],int, void *),
6510				    GLint width, GLint height,
6511				    const void *dataIn, void *dataOut,
6512				    GLint pixelSizeInBytes,
6513				    GLint rowSizeInBytes, GLint isSwap)
6514{
6515   int halfWidth= width / 2;
6516   int halfHeight= height / 2;
6517   const char *src= (const char *) dataIn;
6518   int jj;
6519
6520   assert(width == 1 || height == 1); /* must be 1D */
6521   assert(width != height);	/* can't be square */
6522
6523   if (height == 1) {	/* 1 row */
6524      int outIndex= 0;
6525
6526      assert(width != 1);	/* widthxheight can't be 1x1 */
6527      halfHeight= 1;
6528
6529      /* one horizontal row with possible pad bytes */
6530
6531      for (jj= 0; jj< halfWidth; jj++) {
6532#define BOX2 2
6533	 float totals[4];	/* 4 is maximum components */
6534	 float extractTotals[BOX2][4]; /* 4 is maximum components */
6535	 int cc;
6536
6537	 /* average two at a time, instead of four */
6538	 (*extractPackedPixel)(isSwap,src,
6539			       &extractTotals[0][0]);
6540	 (*extractPackedPixel)(isSwap,(src+pixelSizeInBytes),
6541			       &extractTotals[1][0]);
6542	 for (cc = 0; cc < components; cc++) {
6543	    int kk;
6544
6545	    /* grab 2 pixels to average */
6546	    totals[cc]= 0.0;
6547	    /* totals[RED]= extractTotals[0][RED]+extractTotals[1][RED];
6548	     * totals[RED]/= 2.0;
6549	     */
6550	    for (kk = 0; kk < BOX2; kk++) {
6551	       totals[cc]+= extractTotals[kk][cc];
6552	    }
6553	    totals[cc]/= (float)BOX2;
6554	 }
6555	 (*shovePackedPixel)(totals,outIndex,dataOut);
6556
6557	 outIndex++;
6558	 /* skip over to next group of 2 */
6559	 src+= pixelSizeInBytes + pixelSizeInBytes;
6560      }
6561
6562      {
6563	 int padBytes= rowSizeInBytes - (width*pixelSizeInBytes);
6564	 src+= padBytes;	/* for assertion only */
6565      }
6566      assert(src == &((const char *)dataIn)[rowSizeInBytes]);
6567      assert(outIndex == halfWidth * halfHeight);
6568   }
6569   else if (width == 1) { /* 1 column */
6570      int outIndex= 0;
6571
6572      assert(height != 1);	/* widthxheight can't be 1x1 */
6573      halfWidth= 1;
6574      /* one vertical column with possible pad bytes per row */
6575      /* average two at a time */
6576
6577      for (jj= 0; jj< halfHeight; jj++) {
6578#define BOX2 2
6579	 float totals[4];	/* 4 is maximum components */
6580	 float extractTotals[BOX2][4]; /* 4 is maximum components */
6581	 int cc;
6582
6583	 /* average two at a time, instead of four */
6584	 (*extractPackedPixel)(isSwap,src,
6585			       &extractTotals[0][0]);
6586	 (*extractPackedPixel)(isSwap,(src+rowSizeInBytes),
6587			       &extractTotals[1][0]);
6588	 for (cc = 0; cc < components; cc++) {
6589	    int kk;
6590
6591	    /* grab 2 pixels to average */
6592	    totals[cc]= 0.0;
6593	    /* totals[RED]= extractTotals[0][RED]+extractTotals[1][RED];
6594	     * totals[RED]/= 2.0;
6595	     */
6596	    for (kk = 0; kk < BOX2; kk++) {
6597	       totals[cc]+= extractTotals[kk][cc];
6598	    }
6599	    totals[cc]/= (float)BOX2;
6600	 }
6601	 (*shovePackedPixel)(totals,outIndex,dataOut);
6602
6603	 outIndex++;
6604	 src+= rowSizeInBytes + rowSizeInBytes; /* go to row after next */
6605      }
6606
6607      assert(src == &((const char *)dataIn)[rowSizeInBytes*height]);
6608      assert(outIndex == halfWidth * halfHeight);
6609   }
6610} /* halve1DimagePackedPixel() */
6611
6612/*===========================================================================*/
6613
6614#ifdef RESOLVE_3D_TEXTURE_SUPPORT
6615/*
6616 * This section ensures that GLU 1.3 will load and run on
6617 * a GL 1.1 implementation. It dynamically resolves the
6618 * call to glTexImage3D() which might not be available.
6619 * Or is it might be supported as an extension.
6620 * Contributed by Gerk Huisma <gerk@five-d.demon.nl>.
6621 */
6622
6623typedef void (GLAPIENTRY *TexImage3Dproc)( GLenum target, GLint level,
6624						 GLenum internalFormat,
6625						 GLsizei width, GLsizei height,
6626						 GLsizei depth, GLint border,
6627						 GLenum format, GLenum type,
6628						 const GLvoid *pixels );
6629
6630static TexImage3Dproc pTexImage3D = 0;
6631
6632#if !defined(_WIN32) && !defined(__WIN32__)
6633#  include <dlfcn.h>
6634#  include <sys/types.h>
6635#else
6636  WINGDIAPI PROC  WINAPI wglGetProcAddress(LPCSTR);
6637#endif
6638
6639static void gluTexImage3D( GLenum target, GLint level,
6640			   GLenum internalFormat,
6641			   GLsizei width, GLsizei height,
6642			   GLsizei depth, GLint border,
6643			   GLenum format, GLenum type,
6644			   const GLvoid *pixels )
6645{
6646   if (!pTexImage3D) {
6647#if defined(_WIN32) || defined(__WIN32__)
6648      pTexImage3D = (TexImage3Dproc) wglGetProcAddress("glTexImage3D");
6649      if (!pTexImage3D)
6650	 pTexImage3D = (TexImage3Dproc) wglGetProcAddress("glTexImage3DEXT");
6651#else
6652      void *libHandle = dlopen("libgl.so", RTLD_LAZY);
6653      pTexImage3D = (TexImage3Dproc) dlsym(libHandle, "glTexImage3D" );
6654      if (!pTexImage3D)
6655	 pTexImage3D = (TexImage3Dproc) dlsym(libHandle,"glTexImage3DEXT");
6656      dlclose(libHandle);
6657#endif
6658   }
6659
6660   /* Now call glTexImage3D */
6661   if (pTexImage3D)
6662      pTexImage3D(target, level, internalFormat, width, height,
6663		  depth, border, format, type, pixels);
6664}
6665
6666#else
6667
6668/* Only bind to a GL 1.2 implementation: */
6669#define gluTexImage3D glTexImage3D
6670
6671#endif
6672
6673static GLint imageSize3D(GLint width, GLint height, GLint depth,
6674			 GLenum format, GLenum type)
6675{
6676    int components= elements_per_group(format,type);
6677    int bytes_per_row=	bytes_per_element(type) * width;
6678
6679assert(width > 0 && height > 0 && depth > 0);
6680assert(type != GL_BITMAP);
6681
6682    return bytes_per_row * height * depth * components;
6683} /* imageSize3D() */
6684
6685static void fillImage3D(const PixelStorageModes *psm,
6686			GLint width, GLint height, GLint depth, GLenum format,
6687			GLenum type, GLboolean indexFormat,
6688			const void *userImage, GLushort *newImage)
6689{
6690   int myswapBytes;
6691   int components;
6692   int groupsPerLine;
6693   int elementSize;
6694   int groupSize;
6695   int rowSize;
6696   int padding;
6697   int elementsPerLine;
6698   int rowsPerImage;
6699   int imageSize;
6700   const GLubyte *start, *rowStart, *iter;
6701   GLushort *iter2;
6702   int ww, hh, dd, k;
6703
6704   myswapBytes= psm->unpack_swap_bytes;
6705   components= elements_per_group(format,type);
6706   if (psm->unpack_row_length > 0) {
6707      groupsPerLine= psm->unpack_row_length;
6708   }
6709   else {
6710      groupsPerLine= width;
6711   }
6712   elementSize= bytes_per_element(type);
6713   groupSize= elementSize * components;
6714   if (elementSize == 1) myswapBytes= 0;
6715
6716   /* 3dstuff begin */
6717   if (psm->unpack_image_height > 0) {
6718      rowsPerImage= psm->unpack_image_height;
6719   }
6720   else {
6721      rowsPerImage= height;
6722   }
6723   /* 3dstuff end */
6724
6725   rowSize= groupsPerLine * groupSize;
6726   padding= rowSize % psm->unpack_alignment;
6727   if (padding) {
6728      rowSize+= psm->unpack_alignment - padding;
6729   }
6730
6731   imageSize= rowsPerImage * rowSize; /* 3dstuff */
6732
6733   start= (const GLubyte *)userImage + psm->unpack_skip_rows * rowSize +
6734				 psm->unpack_skip_pixels * groupSize +
6735				 /*3dstuff*/
6736				 psm->unpack_skip_images * imageSize;
6737   elementsPerLine = width * components;
6738
6739   iter2= newImage;
6740   for (dd= 0; dd < depth; dd++) {
6741      rowStart= start;
6742
6743      for (hh= 0; hh < height; hh++) {
6744	 iter= rowStart;
6745
6746	 for (ww= 0; ww < elementsPerLine; ww++) {
6747	    Type_Widget widget;
6748	    float extractComponents[4];
6749
6750	    switch(type) {
6751	    case GL_UNSIGNED_BYTE:
6752	      if (indexFormat) {
6753		  *iter2++ = *iter;
6754	      } else {
6755		  *iter2++ = (*iter) * 257;
6756	      }
6757	      break;
6758	    case GL_BYTE:
6759	      if (indexFormat) {
6760		  *iter2++ = *((const GLbyte *) iter);
6761	      } else {
6762		  /* rough approx */
6763		  *iter2++ = (*((const GLbyte *) iter)) * 516;
6764	      }
6765	      break;
6766	    case GL_UNSIGNED_BYTE_3_3_2:
6767	      extract332(0,iter,extractComponents);
6768	      for (k = 0; k < 3; k++) {
6769		*iter2++ = (GLushort)(extractComponents[k]*65535);
6770	      }
6771	      break;
6772	    case GL_UNSIGNED_BYTE_2_3_3_REV:
6773	      extract233rev(0,iter,extractComponents);
6774	      for (k = 0; k < 3; k++) {
6775		*iter2++ = (GLushort)(extractComponents[k]*65535);
6776	      }
6777	      break;
6778	    case GL_UNSIGNED_SHORT_5_6_5:
6779	      extract565(myswapBytes,iter,extractComponents);
6780	      for (k = 0; k < 3; k++) {
6781		*iter2++ = (GLushort)(extractComponents[k]*65535);
6782	      }
6783	      break;
6784	    case GL_UNSIGNED_SHORT_5_6_5_REV:
6785	      extract565rev(myswapBytes,iter,extractComponents);
6786	      for (k = 0; k < 3; k++) {
6787		*iter2++ = (GLushort)(extractComponents[k]*65535);
6788	      }
6789	      break;
6790	    case GL_UNSIGNED_SHORT_4_4_4_4:
6791	      extract4444(myswapBytes,iter,extractComponents);
6792	      for (k = 0; k < 4; k++) {
6793		*iter2++ = (GLushort)(extractComponents[k]*65535);
6794	      }
6795	      break;
6796	    case GL_UNSIGNED_SHORT_4_4_4_4_REV:
6797	      extract4444rev(myswapBytes,iter,extractComponents);
6798	      for (k = 0; k < 4; k++) {
6799		*iter2++ = (GLushort)(extractComponents[k]*65535);
6800	      }
6801	      break;
6802	    case GL_UNSIGNED_SHORT_5_5_5_1:
6803	      extract5551(myswapBytes,iter,extractComponents);
6804	      for (k = 0; k < 4; k++) {
6805		*iter2++ = (GLushort)(extractComponents[k]*65535);
6806	      }
6807	      break;
6808	    case GL_UNSIGNED_SHORT_1_5_5_5_REV:
6809	      extract1555rev(myswapBytes,iter,extractComponents);
6810	      for (k = 0; k < 4; k++) {
6811		*iter2++ = (GLushort)(extractComponents[k]*65535);
6812	      }
6813	      break;
6814	    case GL_UNSIGNED_SHORT:
6815	    case GL_SHORT:
6816	      if (myswapBytes) {
6817		  widget.ub[0] = iter[1];
6818		  widget.ub[1] = iter[0];
6819	      } else {
6820		  widget.ub[0] = iter[0];
6821		  widget.ub[1] = iter[1];
6822	      }
6823	      if (type == GL_SHORT) {
6824		  if (indexFormat) {
6825		      *iter2++ = widget.s[0];
6826		  } else {
6827		      /* rough approx */
6828		      *iter2++ = widget.s[0]*2;
6829		  }
6830	      } else {
6831		  *iter2++ = widget.us[0];
6832	      }
6833	      break;
6834	    case GL_UNSIGNED_INT_8_8_8_8:
6835	      extract8888(myswapBytes,iter,extractComponents);
6836	      for (k = 0; k < 4; k++) {
6837		*iter2++ = (GLushort)(extractComponents[k]*65535);
6838	      }
6839	      break;
6840	    case GL_UNSIGNED_INT_8_8_8_8_REV:
6841	      extract8888rev(myswapBytes,iter,extractComponents);
6842	      for (k = 0; k < 4; k++) {
6843		*iter2++ = (GLushort)(extractComponents[k]*65535);
6844	      }
6845	      break;
6846	    case GL_UNSIGNED_INT_10_10_10_2:
6847	      extract1010102(myswapBytes,iter,extractComponents);
6848	      for (k = 0; k < 4; k++) {
6849		*iter2++ = (GLushort)(extractComponents[k]*65535);
6850	      }
6851	      break;
6852	    case GL_UNSIGNED_INT_2_10_10_10_REV:
6853	      extract2101010rev(myswapBytes,iter,extractComponents);
6854	      for (k = 0; k < 4; k++) {
6855		*iter2++ = (GLushort)(extractComponents[k]*65535);
6856	      }
6857	      break;
6858	    case GL_INT:
6859	    case GL_UNSIGNED_INT:
6860	    case GL_FLOAT:
6861	      if (myswapBytes) {
6862		  widget.ub[0] = iter[3];
6863		  widget.ub[1] = iter[2];
6864		  widget.ub[2] = iter[1];
6865		  widget.ub[3] = iter[0];
6866	      } else {
6867		  widget.ub[0] = iter[0];
6868		  widget.ub[1] = iter[1];
6869		  widget.ub[2] = iter[2];
6870		  widget.ub[3] = iter[3];
6871	      }
6872	      if (type == GL_FLOAT) {
6873		  if (indexFormat) {
6874		      *iter2++ = widget.f;
6875		  } else {
6876		      *iter2++ = 65535 * widget.f;
6877		  }
6878	      } else if (type == GL_UNSIGNED_INT) {
6879		  if (indexFormat) {
6880		      *iter2++ = widget.ui;
6881		  } else {
6882		      *iter2++ = widget.ui >> 16;
6883		  }
6884	      } else {
6885		  if (indexFormat) {
6886		      *iter2++ = widget.i;
6887		  } else {
6888		      *iter2++ = widget.i >> 15;
6889		  }
6890	      }
6891	      break;
6892	    default:
6893	      assert(0);
6894	    }
6895
6896	    iter+= elementSize;
6897	 } /* for ww */
6898	 rowStart+= rowSize;
6899
6900	 iter= rowStart;	/* for assertion purposes */
6901      } /* for hh */
6902
6903      start+= imageSize;
6904   } /* for dd */
6905
6906   /* iterators should be one byte past end */
6907   if (!isTypePackedPixel(type)) {
6908      assert(iter2 == &newImage[width*height*depth*components]);
6909   }
6910   else {
6911      assert(iter2 == &newImage[width*height*depth*
6912				elements_per_group(format,0)]);
6913   }
6914   assert( iter == &((const GLubyte *)userImage)[rowSize*height*depth +
6915					psm->unpack_skip_rows * rowSize +
6916					psm->unpack_skip_pixels * groupSize +
6917					/*3dstuff*/
6918					psm->unpack_skip_images * imageSize] );
6919} /* fillImage3D () */
6920
6921static void scaleInternal3D(GLint components,
6922			    GLint widthIn, GLint heightIn, GLint depthIn,
6923			    const GLushort *dataIn,
6924			    GLint widthOut, GLint heightOut, GLint depthOut,
6925			    GLushort *dataOut)
6926{
6927    float x, lowx, highx, convx, halfconvx;
6928    float y, lowy, highy, convy, halfconvy;
6929    float z, lowz, highz, convz, halfconvz;
6930    float xpercent,ypercent,zpercent;
6931    float percent;
6932    /* Max components in a format is 4, so... */
6933    float totals[4];
6934    float volume;
6935    int i,j,d,k,zint,yint,xint,xindex,yindex,zindex;
6936    int temp;
6937
6938    convz = (float) depthIn/depthOut;
6939    convy = (float) heightIn/heightOut;
6940    convx = (float) widthIn/widthOut;
6941    halfconvx = convx/2;
6942    halfconvy = convy/2;
6943    halfconvz = convz/2;
6944    for (d = 0; d < depthOut; d++) {
6945       z = convz * (d+0.5);
6946       if (depthIn > depthOut) {
6947	   highz = z + halfconvz;
6948	   lowz = z - halfconvz;
6949       } else {
6950	   highz = z + 0.5;
6951	   lowz = z - 0.5;
6952       }
6953       for (i = 0; i < heightOut; i++) {
6954	   y = convy * (i+0.5);
6955	   if (heightIn > heightOut) {
6956	       highy = y + halfconvy;
6957	       lowy = y - halfconvy;
6958	   } else {
6959	       highy = y + 0.5;
6960	       lowy = y - 0.5;
6961	   }
6962	   for (j = 0; j < widthOut; j++) {
6963	       x = convx * (j+0.5);
6964	       if (widthIn > widthOut) {
6965		   highx = x + halfconvx;
6966		   lowx = x - halfconvx;
6967	       } else {
6968		   highx = x + 0.5;
6969		   lowx = x - 0.5;
6970	       }
6971
6972	       /*
6973	       ** Ok, now apply box filter to box that goes from (lowx, lowy,
6974	       ** lowz) to (highx, highy, highz) on input data into this pixel
6975	       ** on output data.
6976	       */
6977	       totals[0] = totals[1] = totals[2] = totals[3] = 0.0;
6978	       volume = 0.0;
6979
6980	       z = lowz;
6981	       zint = floor(z);
6982	       while (z < highz) {
6983		  zindex = (zint + depthIn) % depthIn;
6984		  if (highz < zint+1) {
6985		      zpercent = highz - z;
6986		  } else {
6987		      zpercent = zint+1 - z;
6988		  }
6989
6990		  y = lowy;
6991		  yint = floor(y);
6992		  while (y < highy) {
6993		      yindex = (yint + heightIn) % heightIn;
6994		      if (highy < yint+1) {
6995			  ypercent = highy - y;
6996		      } else {
6997			  ypercent = yint+1 - y;
6998		      }
6999
7000		      x = lowx;
7001		      xint = floor(x);
7002
7003		      while (x < highx) {
7004			  xindex = (xint + widthIn) % widthIn;
7005			  if (highx < xint+1) {
7006			      xpercent = highx - x;
7007			  } else {
7008			      xpercent = xint+1 - x;
7009			  }
7010
7011			  percent = xpercent * ypercent * zpercent;
7012			  volume += percent;
7013
7014			  temp = (xindex + (yindex*widthIn) +
7015				  (zindex*widthIn*heightIn)) * components;
7016			  for (k = 0; k < components; k++) {
7017			      assert(0 <= (temp+k) &&
7018				     (temp+k) <
7019				     (widthIn*heightIn*depthIn*components));
7020			      totals[k] += dataIn[temp + k] * percent;
7021			  }
7022
7023			  xint++;
7024			  x = xint;
7025		      } /* while x */
7026
7027		      yint++;
7028		      y = yint;
7029		  } /* while y */
7030
7031		  zint++;
7032		  z = zint;
7033	       } /* while z */
7034
7035	       temp = (j + (i * widthOut) +
7036		       (d*widthOut*heightOut)) * components;
7037	       for (k = 0; k < components; k++) {
7038		   /* totals[] should be rounded in the case of enlarging an
7039		    * RGB ramp when the type is 332 or 4444
7040		    */
7041		   assert(0 <= (temp+k) &&
7042			  (temp+k) < (widthOut*heightOut*depthOut*components));
7043		   dataOut[temp + k] = (totals[k]+0.5)/volume;
7044	       }
7045	   } /* for j */
7046       } /* for i */
7047    } /* for d */
7048} /* scaleInternal3D() */
7049
7050static void emptyImage3D(const PixelStorageModes *psm,
7051			 GLint width, GLint height, GLint depth,
7052			 GLenum format, GLenum type, GLboolean indexFormat,
7053			 const GLushort *oldImage, void *userImage)
7054{
7055   int myswapBytes;
7056   int components;
7057   int groupsPerLine;
7058   int elementSize;
7059   int groupSize;
7060   int rowSize;
7061   int padding;
7062   GLubyte *start, *rowStart, *iter;
7063   int elementsPerLine;
7064   const GLushort *iter2;
7065   int ii, jj, dd, k;
7066   int rowsPerImage;
7067   int imageSize;
7068
7069   myswapBytes= psm->pack_swap_bytes;
7070   components = elements_per_group(format,type);
7071   if (psm->pack_row_length > 0) {
7072      groupsPerLine = psm->pack_row_length;
7073   }
7074   else {
7075      groupsPerLine = width;
7076   }
7077
7078   elementSize= bytes_per_element(type);
7079   groupSize= elementSize * components;
7080   if (elementSize == 1) myswapBytes= 0;
7081
7082   /* 3dstuff begin */
7083   if (psm->pack_image_height > 0) {
7084      rowsPerImage= psm->pack_image_height;
7085   }
7086   else {
7087      rowsPerImage= height;
7088   }
7089
7090   /* 3dstuff end */
7091
7092   rowSize = groupsPerLine * groupSize;
7093   padding = rowSize % psm->pack_alignment;
7094   if (padding) {
7095      rowSize+= psm->pack_alignment - padding;
7096   }
7097
7098   imageSize= rowsPerImage * rowSize; /* 3dstuff */
7099
7100   start = (GLubyte *)userImage + psm->pack_skip_rows * rowSize +
7101				  psm->pack_skip_pixels * groupSize +
7102				  /*3dstuff*/
7103				  psm->pack_skip_images * imageSize;
7104   elementsPerLine= width * components;
7105
7106   iter2 = oldImage;
7107   for (dd= 0; dd < depth; dd++) {
7108      rowStart= start;
7109
7110      for (ii= 0; ii< height; ii++) {
7111	 iter = rowStart;
7112
7113	 for (jj = 0; jj < elementsPerLine; jj++) {
7114	    Type_Widget widget;
7115	    float shoveComponents[4];
7116
7117	    switch(type){
7118	    case GL_UNSIGNED_BYTE:
7119	      if (indexFormat) {
7120		  *iter = *iter2++;
7121	      } else {
7122		  *iter = *iter2++ >> 8;
7123	      }
7124	      break;
7125	    case GL_BYTE:
7126	      if (indexFormat) {
7127		  *((GLbyte *) iter) = *iter2++;
7128	      } else {
7129		  *((GLbyte *) iter) = *iter2++ >> 9;
7130	      }
7131	      break;
7132	    case GL_UNSIGNED_BYTE_3_3_2:
7133	      for (k = 0; k < 3; k++) {
7134		 shoveComponents[k]= *iter2++ / 65535.0;
7135	      }
7136	      shove332(shoveComponents,0,(void *)iter);
7137	      break;
7138	    case GL_UNSIGNED_BYTE_2_3_3_REV:
7139	      for (k = 0; k < 3; k++) {
7140		 shoveComponents[k]= *iter2++ / 65535.0;
7141	      }
7142	      shove233rev(shoveComponents,0,(void *)iter);
7143	      break;
7144	    case GL_UNSIGNED_SHORT_5_6_5:
7145	      for (k = 0; k < 3; k++) {
7146		 shoveComponents[k]= *iter2++ / 65535.0;
7147	      }
7148	      shove565(shoveComponents,0,(void *)&widget.us[0]);
7149	      if (myswapBytes) {
7150		 iter[0] = widget.ub[1];
7151		 iter[1] = widget.ub[0];
7152	      }
7153	      else {
7154		 *(GLushort *)iter = widget.us[0];
7155	      }
7156	      break;
7157	    case GL_UNSIGNED_SHORT_5_6_5_REV:
7158	      for (k = 0; k < 3; k++) {
7159		 shoveComponents[k]= *iter2++ / 65535.0;
7160	      }
7161	      shove565rev(shoveComponents,0,(void *)&widget.us[0]);
7162	      if (myswapBytes) {
7163		 iter[0] = widget.ub[1];
7164		 iter[1] = widget.ub[0];
7165	      }
7166	      else {
7167		 *(GLushort *)iter = widget.us[0];
7168	      }
7169	      break;
7170	    case GL_UNSIGNED_SHORT_4_4_4_4:
7171	      for (k = 0; k < 4; k++) {
7172		 shoveComponents[k]= *iter2++ / 65535.0;
7173	      }
7174	      shove4444(shoveComponents,0,(void *)&widget.us[0]);
7175	      if (myswapBytes) {
7176		 iter[0] = widget.ub[1];
7177		 iter[1] = widget.ub[0];
7178	      } else {
7179		 *(GLushort *)iter = widget.us[0];
7180	      }
7181	      break;
7182	    case GL_UNSIGNED_SHORT_4_4_4_4_REV:
7183	      for (k = 0; k < 4; k++) {
7184		 shoveComponents[k]= *iter2++ / 65535.0;
7185	      }
7186	      shove4444rev(shoveComponents,0,(void *)&widget.us[0]);
7187	      if (myswapBytes) {
7188		 iter[0] = widget.ub[1];
7189		 iter[1] = widget.ub[0];
7190	      } else {
7191		 *(GLushort *)iter = widget.us[0];
7192	      }
7193	      break;
7194	    case GL_UNSIGNED_SHORT_5_5_5_1:
7195	      for (k = 0; k < 4; k++) {
7196		 shoveComponents[k]= *iter2++ / 65535.0;
7197	      }
7198	      shove5551(shoveComponents,0,(void *)&widget.us[0]);
7199	      if (myswapBytes) {
7200		 iter[0] = widget.ub[1];
7201		 iter[1] = widget.ub[0];
7202	      } else {
7203		 *(GLushort *)iter = widget.us[0];
7204	      }
7205	      break;
7206	    case GL_UNSIGNED_SHORT_1_5_5_5_REV:
7207	      for (k = 0; k < 4; k++) {
7208		 shoveComponents[k]= *iter2++ / 65535.0;
7209	      }
7210	      shove1555rev(shoveComponents,0,(void *)&widget.us[0]);
7211	      if (myswapBytes) {
7212		 iter[0] = widget.ub[1];
7213		 iter[1] = widget.ub[0];
7214	      } else {
7215		 *(GLushort *)iter = widget.us[0];
7216	      }
7217	      break;
7218	    case GL_UNSIGNED_SHORT:
7219	    case GL_SHORT:
7220	      if (type == GL_SHORT) {
7221		  if (indexFormat) {
7222		      widget.s[0] = *iter2++;
7223		  } else {
7224		      widget.s[0] = *iter2++ >> 1;
7225		  }
7226	      } else {
7227		  widget.us[0] = *iter2++;
7228	      }
7229	      if (myswapBytes) {
7230		  iter[0] = widget.ub[1];
7231		  iter[1] = widget.ub[0];
7232	      } else {
7233		  iter[0] = widget.ub[0];
7234		  iter[1] = widget.ub[1];
7235	      }
7236	      break;
7237	    case GL_UNSIGNED_INT_8_8_8_8:
7238	       for (k = 0; k < 4; k++) {
7239		  shoveComponents[k]= *iter2++ / 65535.0;
7240	       }
7241	       shove8888(shoveComponents,0,(void *)&widget.ui);
7242	       if (myswapBytes) {
7243		   iter[3] = widget.ub[0];
7244		   iter[2] = widget.ub[1];
7245		   iter[1] = widget.ub[2];
7246		   iter[0] = widget.ub[3];
7247	       } else {
7248		   *(GLuint *)iter= widget.ui;
7249	       }
7250	       break;
7251	    case GL_UNSIGNED_INT_8_8_8_8_REV:
7252	       for (k = 0; k < 4; k++) {
7253		  shoveComponents[k]= *iter2++ / 65535.0;
7254	       }
7255	       shove8888rev(shoveComponents,0,(void *)&widget.ui);
7256	       if (myswapBytes) {
7257		   iter[3] = widget.ub[0];
7258		   iter[2] = widget.ub[1];
7259		   iter[1] = widget.ub[2];
7260		   iter[0] = widget.ub[3];
7261	       } else {
7262		   *(GLuint *)iter= widget.ui;
7263	       }
7264	       break;
7265	    case GL_UNSIGNED_INT_10_10_10_2:
7266	       for (k = 0; k < 4; k++) {
7267		  shoveComponents[k]= *iter2++ / 65535.0;
7268	       }
7269	       shove1010102(shoveComponents,0,(void *)&widget.ui);
7270	       if (myswapBytes) {
7271		   iter[3] = widget.ub[0];
7272		   iter[2] = widget.ub[1];
7273		   iter[1] = widget.ub[2];
7274		   iter[0] = widget.ub[3];
7275	       } else {
7276		   *(GLuint *)iter= widget.ui;
7277	       }
7278	       break;
7279	    case GL_UNSIGNED_INT_2_10_10_10_REV:
7280	       for (k = 0; k < 4; k++) {
7281		  shoveComponents[k]= *iter2++ / 65535.0;
7282	       }
7283	       shove2101010rev(shoveComponents,0,(void *)&widget.ui);
7284	       if (myswapBytes) {
7285		   iter[3] = widget.ub[0];
7286		   iter[2] = widget.ub[1];
7287		   iter[1] = widget.ub[2];
7288		   iter[0] = widget.ub[3];
7289	       } else {
7290		   *(GLuint *)iter= widget.ui;
7291	       }
7292	       break;
7293	    case GL_INT:
7294	    case GL_UNSIGNED_INT:
7295	    case GL_FLOAT:
7296	      if (type == GL_FLOAT) {
7297		  if (indexFormat) {
7298		      widget.f = *iter2++;
7299		  } else {
7300		      widget.f = *iter2++ / (float) 65535.0;
7301		  }
7302	      } else if (type == GL_UNSIGNED_INT) {
7303		  if (indexFormat) {
7304		      widget.ui = *iter2++;
7305		  } else {
7306		      widget.ui = (unsigned int) *iter2++ * 65537;
7307		  }
7308	      } else {
7309		  if (indexFormat) {
7310		      widget.i = *iter2++;
7311		  } else {
7312		      widget.i = ((unsigned int) *iter2++ * 65537)/2;
7313		  }
7314	      }
7315	      if (myswapBytes) {
7316		  iter[3] = widget.ub[0];
7317		  iter[2] = widget.ub[1];
7318		  iter[1] = widget.ub[2];
7319		  iter[0] = widget.ub[3];
7320	      } else {
7321		  iter[0] = widget.ub[0];
7322		  iter[1] = widget.ub[1];
7323		  iter[2] = widget.ub[2];
7324		  iter[3] = widget.ub[3];
7325	      }
7326	      break;
7327	    default:
7328	       assert(0);
7329	    }
7330
7331	    iter+= elementSize;
7332	 }  /* for jj */
7333
7334	 rowStart+= rowSize;
7335      } /* for ii */
7336
7337      start+= imageSize;
7338   } /* for dd */
7339
7340   /* iterators should be one byte past end */
7341   if (!isTypePackedPixel(type)) {
7342      assert(iter2 == &oldImage[width*height*depth*components]);
7343   }
7344   else {
7345      assert(iter2 == &oldImage[width*height*depth*
7346				elements_per_group(format,0)]);
7347   }
7348   assert( iter == &((GLubyte *)userImage)[rowSize*height*depth +
7349					psm->unpack_skip_rows * rowSize +
7350					psm->unpack_skip_pixels * groupSize +
7351					/*3dstuff*/
7352					psm->unpack_skip_images * imageSize] );
7353} /* emptyImage3D() */
7354
7355static
7356int gluScaleImage3D(GLenum format,
7357		    GLint widthIn, GLint heightIn, GLint depthIn,
7358		    GLenum typeIn, const void *dataIn,
7359		    GLint widthOut, GLint heightOut, GLint depthOut,
7360		    GLenum typeOut, void *dataOut)
7361{
7362   int components;
7363   GLushort *beforeImage, *afterImage;
7364   PixelStorageModes psm;
7365
7366   if (widthIn == 0 || heightIn == 0 || depthIn == 0 ||
7367       widthOut == 0 || heightOut == 0 || depthOut == 0) {
7368      return 0;
7369   }
7370
7371   if (widthIn < 0 || heightIn < 0 || depthIn < 0 ||
7372       widthOut < 0 || heightOut < 0 || depthOut < 0) {
7373      return GLU_INVALID_VALUE;
7374   }
7375
7376   if (!legalFormat(format) || !legalType(typeIn) || !legalType(typeOut) ||
7377       typeIn == GL_BITMAP || typeOut == GL_BITMAP) {
7378      return GLU_INVALID_ENUM;
7379   }
7380   if (!isLegalFormatForPackedPixelType(format, typeIn)) {
7381      return GLU_INVALID_OPERATION;
7382   }
7383   if (!isLegalFormatForPackedPixelType(format, typeOut)) {
7384      return GLU_INVALID_OPERATION;
7385   }
7386
7387   beforeImage = malloc(imageSize3D(widthIn, heightIn, depthIn, format,
7388				    GL_UNSIGNED_SHORT));
7389   afterImage = malloc(imageSize3D(widthOut, heightOut, depthOut, format,
7390				   GL_UNSIGNED_SHORT));
7391   if (beforeImage == NULL || afterImage == NULL) {
7392       free(beforeImage);
7393       free(afterImage);
7394       return GLU_OUT_OF_MEMORY;
7395   }
7396   retrieveStoreModes3D(&psm);
7397
7398   fillImage3D(&psm,widthIn,heightIn,depthIn,format,typeIn, is_index(format),
7399	       dataIn, beforeImage);
7400   components = elements_per_group(format,0);
7401   scaleInternal3D(components,widthIn,heightIn,depthIn,beforeImage,
7402		   widthOut,heightOut,depthOut,afterImage);
7403   emptyImage3D(&psm,widthOut,heightOut,depthOut,format,typeOut,
7404		is_index(format),afterImage, dataOut);
7405   free((void *) beforeImage);
7406   free((void *) afterImage);
7407
7408   return 0;
7409} /* gluScaleImage3D() */
7410
7411
7412static void closestFit3D(GLenum target, GLint width, GLint height, GLint depth,
7413			 GLint internalFormat, GLenum format, GLenum type,
7414			 GLint *newWidth, GLint *newHeight, GLint *newDepth)
7415{
7416   GLint widthPowerOf2= nearestPower(width);
7417   GLint heightPowerOf2= nearestPower(height);
7418   GLint depthPowerOf2= nearestPower(depth);
7419   GLint proxyWidth;
7420
7421   do {
7422      /* compute level 1 width & height & depth, clamping each at 1 */
7423      GLint widthAtLevelOne= (widthPowerOf2 > 1) ?
7424			      widthPowerOf2 >> 1 :
7425			      widthPowerOf2;
7426      GLint heightAtLevelOne= (heightPowerOf2 > 1) ?
7427			       heightPowerOf2 >> 1 :
7428			       heightPowerOf2;
7429      GLint depthAtLevelOne= (depthPowerOf2 > 1) ?
7430			      depthPowerOf2 >> 1 :
7431			      depthPowerOf2;
7432      GLenum proxyTarget = GL_PROXY_TEXTURE_3D;
7433      assert(widthAtLevelOne > 0);
7434      assert(heightAtLevelOne > 0);
7435      assert(depthAtLevelOne > 0);
7436
7437      /* does width x height x depth at level 1 & all their mipmaps fit? */
7438      assert(target == GL_TEXTURE_3D || target == GL_PROXY_TEXTURE_3D);
7439      gluTexImage3D(proxyTarget, 1, /* must be non-zero */
7440                    internalFormat,
7441                    widthAtLevelOne,heightAtLevelOne,depthAtLevelOne,
7442                    0,format,type,NULL);
7443      glGetTexLevelParameteriv(proxyTarget, 1,GL_TEXTURE_WIDTH,&proxyWidth);
7444      /* does it fit??? */
7445      if (proxyWidth == 0) { /* nope, so try again with these sizes */
7446	 if (widthPowerOf2 == 1 && heightPowerOf2 == 1 &&
7447	     depthPowerOf2 == 1) {
7448	    *newWidth= *newHeight= *newDepth= 1; /* must fit 1x1x1 texture */
7449	    return;
7450	 }
7451	 widthPowerOf2= widthAtLevelOne;
7452	 heightPowerOf2= heightAtLevelOne;
7453	 depthPowerOf2= depthAtLevelOne;
7454      }
7455      /* else it does fit */
7456   } while (proxyWidth == 0);
7457   /* loop must terminate! */
7458
7459   /* return the width & height at level 0 that fits */
7460   *newWidth= widthPowerOf2;
7461   *newHeight= heightPowerOf2;
7462   *newDepth= depthPowerOf2;
7463/*printf("Proxy Textures\n");*/
7464} /* closestFit3D() */
7465
7466static void halveImagePackedPixelSlice(int components,
7467				       void (*extractPackedPixel)
7468				       (int, const void *,GLfloat []),
7469				       void (*shovePackedPixel)
7470				       (const GLfloat [],int, void *),
7471				       GLint width, GLint height, GLint depth,
7472				       const void *dataIn, void *dataOut,
7473				       GLint pixelSizeInBytes,
7474				       GLint rowSizeInBytes,
7475				       GLint imageSizeInBytes,
7476				       GLint isSwap)
7477{
7478   int ii, jj;
7479   int halfWidth= width / 2;
7480   int halfHeight= height / 2;
7481   int halfDepth= depth / 2;
7482   const char *src= (const char *)dataIn;
7483   int outIndex= 0;
7484
7485   assert((width == 1 || height == 1) && depth >= 2);
7486
7487   if (width == height) {	/* a 1-pixel column viewed from top */
7488      assert(width == 1 && height == 1);
7489      assert(depth >= 2);
7490
7491      for (ii= 0; ii< halfDepth; ii++) {
7492	 float totals[4];
7493	 float extractTotals[BOX2][4];
7494	 int cc;
7495
7496	 (*extractPackedPixel)(isSwap,src,&extractTotals[0][0]);
7497	 (*extractPackedPixel)(isSwap,(src+imageSizeInBytes),
7498			       &extractTotals[1][0]);
7499	 for (cc = 0; cc < components; cc++) {
7500	    int kk;
7501
7502	    /* average 2 pixels since only a column */
7503	    totals[cc]= 0.0;
7504	    /* totals[RED]= extractTotals[0][RED]+extractTotals[1][RED];
7505	     * totals[RED]/= 2.0;
7506	     */
7507	    for (kk = 0; kk < BOX2; kk++) {
7508	      totals[cc]+= extractTotals[kk][cc];
7509	    }
7510	    totals[cc]/= (float)BOX2;
7511	 } /* for cc */
7512
7513	 (*shovePackedPixel)(totals,outIndex,dataOut);
7514	 outIndex++;
7515	 /* skip over to next group of 2 */
7516	 src+= imageSizeInBytes + imageSizeInBytes;
7517      } /* for ii */
7518   }
7519   else if (height == 1) {	/* horizontal slice viewed from top */
7520      assert(width != 1);
7521
7522      for (ii= 0; ii< halfDepth; ii++) {
7523	 for (jj= 0; jj< halfWidth; jj++) {
7524	     float totals[4];
7525	     float extractTotals[BOX4][4];
7526	     int cc;
7527
7528	     (*extractPackedPixel)(isSwap,src,
7529				   &extractTotals[0][0]);
7530	     (*extractPackedPixel)(isSwap,(src+pixelSizeInBytes),
7531				   &extractTotals[1][0]);
7532	     (*extractPackedPixel)(isSwap,(src+imageSizeInBytes),
7533				   &extractTotals[2][0]);
7534	     (*extractPackedPixel)(isSwap,
7535				   (src+imageSizeInBytes+pixelSizeInBytes),
7536				   &extractTotals[3][0]);
7537	     for (cc = 0; cc < components; cc++) {
7538		int kk;
7539
7540		/* grab 4 pixels to average */
7541		totals[cc]= 0.0;
7542		/* totals[RED]= extractTotals[0][RED]+extractTotals[1][RED]+
7543		 *		extractTotals[2][RED]+extractTotals[3][RED];
7544		 * totals[RED]/= 4.0;
7545		 */
7546		for (kk = 0; kk < BOX4; kk++) {
7547		   totals[cc]+= extractTotals[kk][cc];
7548		}
7549		totals[cc]/= (float)BOX4;
7550	     }
7551	     (*shovePackedPixel)(totals,outIndex,dataOut);
7552
7553	     outIndex++;
7554	     /* skip over to next horizontal square of 4 */
7555	     src+= imageSizeInBytes + imageSizeInBytes;
7556	 }
7557      }
7558
7559      /* assert() */
7560   }
7561   else if (width == 1) {	/* vertical slice viewed from top */
7562      assert(height != 1);
7563
7564      for (ii= 0; ii< halfDepth; ii++) {
7565	 for (jj= 0; jj< halfHeight; jj++) {
7566	    float totals[4];
7567	    float extractTotals[BOX4][4];
7568	    int cc;
7569
7570	    (*extractPackedPixel)(isSwap,src,
7571				  &extractTotals[0][0]);
7572	    (*extractPackedPixel)(isSwap,(src+rowSizeInBytes),
7573				  &extractTotals[1][0]);
7574	    (*extractPackedPixel)(isSwap,(src+imageSizeInBytes),
7575				  &extractTotals[2][0]);
7576	    (*extractPackedPixel)(isSwap,
7577				  (src+imageSizeInBytes+rowSizeInBytes),
7578				  &extractTotals[3][0]);
7579	    for (cc = 0; cc < components; cc++) {
7580	       int kk;
7581
7582	       /* grab 4 pixels to average */
7583	       totals[cc]= 0.0;
7584	       /* totals[RED]= extractTotals[0][RED]+extractTotals[1][RED]+
7585		*	       extractTotals[2][RED]+extractTotals[3][RED];
7586		* totals[RED]/= 4.0;
7587		*/
7588	       for (kk = 0; kk < BOX4; kk++) {
7589		  totals[cc]+= extractTotals[kk][cc];
7590	       }
7591	       totals[cc]/= (float)BOX4;
7592	    }
7593	    (*shovePackedPixel)(totals,outIndex,dataOut);
7594
7595	    outIndex++;
7596
7597	    /* skip over to next vertical square of 4 */
7598	    src+= imageSizeInBytes + imageSizeInBytes;
7599	 }
7600      }
7601      /* assert() */
7602   }
7603
7604} /* halveImagePackedPixelSlice() */
7605
7606static void halveImagePackedPixel3D(int components,
7607				    void (*extractPackedPixel)
7608				    (int, const void *,GLfloat []),
7609				    void (*shovePackedPixel)
7610				    (const GLfloat [],int, void *),
7611				    GLint width, GLint height, GLint depth,
7612				    const void *dataIn, void *dataOut,
7613				    GLint pixelSizeInBytes,
7614				    GLint rowSizeInBytes,
7615				    GLint imageSizeInBytes,
7616				    GLint isSwap)
7617{
7618   if (depth == 1) {
7619      assert(1 <= width && 1 <= height);
7620
7621      halveImagePackedPixel(components,extractPackedPixel,shovePackedPixel,
7622			    width,height,dataIn,dataOut,pixelSizeInBytes,
7623			    rowSizeInBytes,isSwap);
7624      return;
7625   }
7626   /* a horizontal or vertical slice viewed from top */
7627   else if (width == 1 || height == 1) {
7628      assert(1 <= depth);
7629
7630      halveImagePackedPixelSlice(components,
7631				 extractPackedPixel,shovePackedPixel,
7632				 width, height, depth, dataIn, dataOut,
7633				 pixelSizeInBytes, rowSizeInBytes,
7634				 imageSizeInBytes, isSwap);
7635      return;
7636   }
7637   {
7638      int ii, jj, dd;
7639
7640      int halfWidth= width / 2;
7641      int halfHeight= height / 2;
7642      int halfDepth= depth / 2;
7643      const char *src= (const char *) dataIn;
7644      int padBytes= rowSizeInBytes - (width*pixelSizeInBytes);
7645      int outIndex= 0;
7646
7647      for (dd= 0; dd < halfDepth; dd++) {
7648	 for (ii= 0; ii< halfHeight; ii++) {
7649	    for (jj= 0; jj< halfWidth; jj++) {
7650#define BOX8 8
7651	       float totals[4]; /* 4 is maximum components */
7652	       float extractTotals[BOX8][4]; /* 4 is maximum components */
7653	       int cc;
7654
7655	       (*extractPackedPixel)(isSwap,src,
7656				     &extractTotals[0][0]);
7657	       (*extractPackedPixel)(isSwap,(src+pixelSizeInBytes),
7658				     &extractTotals[1][0]);
7659	       (*extractPackedPixel)(isSwap,(src+rowSizeInBytes),
7660				     &extractTotals[2][0]);
7661	       (*extractPackedPixel)(isSwap,
7662				     (src+rowSizeInBytes+pixelSizeInBytes),
7663				     &extractTotals[3][0]);
7664
7665	       (*extractPackedPixel)(isSwap,(src+imageSizeInBytes),
7666				     &extractTotals[4][0]);
7667	       (*extractPackedPixel)(isSwap,(src+pixelSizeInBytes+imageSizeInBytes),
7668				     &extractTotals[5][0]);
7669	       (*extractPackedPixel)(isSwap,(src+rowSizeInBytes+imageSizeInBytes),
7670				     &extractTotals[6][0]);
7671	       (*extractPackedPixel)(isSwap,
7672				     (src+rowSizeInBytes+pixelSizeInBytes+imageSizeInBytes),
7673				     &extractTotals[7][0]);
7674	       for (cc = 0; cc < components; cc++) {
7675		  int kk;
7676
7677		  /* grab 8 pixels to average */
7678		  totals[cc]= 0.0;
7679		  /* totals[RED]= extractTotals[0][RED]+extractTotals[1][RED]+
7680		   *		  extractTotals[2][RED]+extractTotals[3][RED]+
7681		   *		  extractTotals[4][RED]+extractTotals[5][RED]+
7682		   *		  extractTotals[6][RED]+extractTotals[7][RED];
7683		   * totals[RED]/= 8.0;
7684		   */
7685		  for (kk = 0; kk < BOX8; kk++) {
7686		     totals[cc]+= extractTotals[kk][cc];
7687		  }
7688		  totals[cc]/= (float)BOX8;
7689	       }
7690	       (*shovePackedPixel)(totals,outIndex,dataOut);
7691
7692	       outIndex++;
7693	       /* skip over to next square of 4 */
7694	       src+= pixelSizeInBytes + pixelSizeInBytes;
7695	    }
7696	    /* skip past pad bytes, if any, to get to next row */
7697	    src+= padBytes;
7698
7699	    /* src is at beginning of a row here, but it's the second row of
7700	     * the square block of 4 pixels that we just worked on so we
7701	     * need to go one more row.
7702	     * i.e.,
7703	     *			 OO...
7704	     *		 here -->OO...
7705	     *	     but want -->OO...
7706	     *			 OO...
7707	     *			 ...
7708	     */
7709	    src+= rowSizeInBytes;
7710	 }
7711
7712	 src+= imageSizeInBytes;
7713      } /* for dd */
7714
7715      /* both pointers must reach one byte after the end */
7716      assert(src == &((const char *)dataIn)[rowSizeInBytes*height*depth]);
7717      assert(outIndex == halfWidth * halfHeight * halfDepth);
7718   } /* for dd */
7719
7720} /* halveImagePackedPixel3D() */
7721
7722static int gluBuild3DMipmapLevelsCore(GLenum target, GLint internalFormat,
7723				      GLsizei width,
7724				      GLsizei height,
7725				      GLsizei depth,
7726				      GLsizei widthPowerOf2,
7727				      GLsizei heightPowerOf2,
7728				      GLsizei depthPowerOf2,
7729				      GLenum format, GLenum type,
7730				      GLint userLevel,
7731				      GLint baseLevel,GLint maxLevel,
7732				      const void *data)
7733{
7734   GLint newWidth, newHeight, newDepth;
7735   GLint level, levels;
7736   const void *usersImage;
7737   void *srcImage, *dstImage;
7738   __GLU_INIT_SWAP_IMAGE;
7739   GLint memReq;
7740   GLint cmpts;
7741
7742   GLint myswapBytes, groupsPerLine, elementSize, groupSize;
7743   GLint rowsPerImage, imageSize;
7744   GLint rowSize, padding;
7745   PixelStorageModes psm;
7746
7747   assert(checkMipmapArgs(internalFormat,format,type) == 0);
7748   assert(width >= 1 && height >= 1 && depth >= 1);
7749   assert(type != GL_BITMAP);
7750
7751   srcImage = dstImage = NULL;
7752
7753   newWidth= widthPowerOf2;
7754   newHeight= heightPowerOf2;
7755   newDepth= depthPowerOf2;
7756   levels = computeLog(newWidth);
7757   level = computeLog(newHeight);
7758   if (level > levels) levels=level;
7759   level = computeLog(newDepth);
7760   if (level > levels) levels=level;
7761
7762   levels+= userLevel;
7763
7764   retrieveStoreModes3D(&psm);
7765   myswapBytes = psm.unpack_swap_bytes;
7766   cmpts = elements_per_group(format,type);
7767   if (psm.unpack_row_length > 0) {
7768       groupsPerLine = psm.unpack_row_length;
7769   } else {
7770       groupsPerLine = width;
7771   }
7772
7773   elementSize = bytes_per_element(type);
7774   groupSize = elementSize * cmpts;
7775   if (elementSize == 1) myswapBytes = 0;
7776
7777   /* 3dstuff begin */
7778   if (psm.unpack_image_height > 0) {
7779      rowsPerImage= psm.unpack_image_height;
7780   }
7781   else {
7782      rowsPerImage= height;
7783   }
7784
7785   /* 3dstuff end */
7786   rowSize = groupsPerLine * groupSize;
7787   padding = (rowSize % psm.unpack_alignment);
7788   if (padding) {
7789       rowSize += psm.unpack_alignment - padding;
7790   }
7791
7792   imageSize= rowsPerImage * rowSize; /* 3dstuff */
7793
7794   usersImage = (const GLubyte *)data + psm.unpack_skip_rows * rowSize +
7795				  psm.unpack_skip_pixels * groupSize +
7796				  /* 3dstuff */
7797				  psm.unpack_skip_images * imageSize;
7798
7799   glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
7800   glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
7801   glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
7802   glPixelStorei(GL_UNPACK_SKIP_IMAGES, 0);
7803   glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, 0);
7804
7805   level = userLevel;
7806
7807   if (width == newWidth && height == newHeight && depth == newDepth) {
7808       /* Use usersImage for level userLevel */
7809       if (baseLevel <= level && level <= maxLevel) {
7810	  gluTexImage3D(target, level, internalFormat, width,
7811		       height, depth, 0, format, type,
7812		       usersImage);
7813       }
7814       if(levels == 0) { /* we're done. clean up and return */
7815	 glPixelStorei(GL_UNPACK_ALIGNMENT, psm.unpack_alignment);
7816	 glPixelStorei(GL_UNPACK_SKIP_ROWS, psm.unpack_skip_rows);
7817	 glPixelStorei(GL_UNPACK_SKIP_PIXELS, psm.unpack_skip_pixels);
7818	 glPixelStorei(GL_UNPACK_ROW_LENGTH, psm.unpack_row_length);
7819	 glPixelStorei(GL_UNPACK_SWAP_BYTES, psm.unpack_swap_bytes);
7820	 glPixelStorei(GL_UNPACK_SKIP_IMAGES, psm.unpack_skip_images);
7821	 glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, psm.unpack_image_height);
7822	 return 0;
7823       }
7824       {
7825	  int nextWidth= newWidth/2;
7826	  int nextHeight= newHeight/2;
7827	  int nextDepth= newDepth/2;
7828
7829	  /* clamp to 1 */
7830	  if (nextWidth < 1) nextWidth= 1;
7831	  if (nextHeight < 1) nextHeight= 1;
7832	  if (nextDepth < 1) nextDepth= 1;
7833       memReq = imageSize3D(nextWidth, nextHeight, nextDepth, format, type);
7834       }
7835       switch(type) {
7836       case GL_UNSIGNED_BYTE:
7837	 dstImage = (GLubyte *)malloc(memReq);
7838	 break;
7839       case GL_BYTE:
7840	 dstImage = (GLbyte *)malloc(memReq);
7841	 break;
7842       case GL_UNSIGNED_SHORT:
7843	 dstImage = (GLushort *)malloc(memReq);
7844	 break;
7845       case GL_SHORT:
7846	 dstImage = (GLshort *)malloc(memReq);
7847	 break;
7848       case GL_UNSIGNED_INT:
7849	 dstImage = (GLuint *)malloc(memReq);
7850	 break;
7851       case GL_INT:
7852	 dstImage = (GLint *)malloc(memReq);
7853	 break;
7854       case GL_FLOAT:
7855	 dstImage = (GLfloat *)malloc(memReq);
7856	 break;
7857       case GL_UNSIGNED_BYTE_3_3_2:
7858       case GL_UNSIGNED_BYTE_2_3_3_REV:
7859	 dstImage = (GLubyte *)malloc(memReq);
7860	 break;
7861       case GL_UNSIGNED_SHORT_5_6_5:
7862       case GL_UNSIGNED_SHORT_5_6_5_REV:
7863       case GL_UNSIGNED_SHORT_4_4_4_4:
7864       case GL_UNSIGNED_SHORT_4_4_4_4_REV:
7865       case GL_UNSIGNED_SHORT_5_5_5_1:
7866       case GL_UNSIGNED_SHORT_1_5_5_5_REV:
7867	 dstImage = (GLushort *)malloc(memReq);
7868	 break;
7869       case GL_UNSIGNED_INT_8_8_8_8:
7870       case GL_UNSIGNED_INT_8_8_8_8_REV:
7871       case GL_UNSIGNED_INT_10_10_10_2:
7872       case GL_UNSIGNED_INT_2_10_10_10_REV:
7873	 dstImage = (GLuint *)malloc(memReq);
7874	 break;
7875       default:
7876	 return GLU_INVALID_ENUM; /* assertion */
7877       }
7878       if (dstImage == NULL) {
7879	 glPixelStorei(GL_UNPACK_ALIGNMENT, psm.unpack_alignment);
7880	 glPixelStorei(GL_UNPACK_SKIP_ROWS, psm.unpack_skip_rows);
7881	 glPixelStorei(GL_UNPACK_SKIP_PIXELS, psm.unpack_skip_pixels);
7882	 glPixelStorei(GL_UNPACK_ROW_LENGTH, psm.unpack_row_length);
7883	 glPixelStorei(GL_UNPACK_SWAP_BYTES, psm.unpack_swap_bytes);
7884	 glPixelStorei(GL_UNPACK_SKIP_IMAGES, psm.unpack_skip_images);
7885	 glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, psm.unpack_image_height);
7886	 return GLU_OUT_OF_MEMORY;
7887       }
7888       else
7889	 switch(type) {
7890	 case GL_UNSIGNED_BYTE:
7891	   if (depth > 1) {
7892	     halveImage3D(cmpts,extractUbyte,shoveUbyte,
7893			  width,height,depth,
7894			  usersImage,dstImage,elementSize,groupSize,rowSize,
7895			  imageSize,myswapBytes);
7896	   }
7897	   else {
7898	     halveImage_ubyte(cmpts,width,height,usersImage,dstImage,
7899			      elementSize,rowSize,groupSize);
7900	   }
7901	   break;
7902	 case GL_BYTE:
7903	   if (depth > 1) {
7904	   halveImage3D(cmpts,extractSbyte,shoveSbyte,
7905			width,height,depth,
7906			usersImage,dstImage,elementSize,groupSize,rowSize,
7907			imageSize,myswapBytes);
7908	   }
7909	   else {
7910	     halveImage_byte(cmpts,width,height,usersImage,dstImage,
7911			     elementSize,rowSize,groupSize);
7912	   }
7913	   break;
7914	 case GL_UNSIGNED_SHORT:
7915	   if (depth > 1) {
7916	   halveImage3D(cmpts,extractUshort,shoveUshort,
7917			width,height,depth,
7918			usersImage,dstImage,elementSize,groupSize,rowSize,
7919			imageSize,myswapBytes);
7920	   }
7921	   else {
7922	     halveImage_ushort(cmpts,width,height,usersImage,dstImage,
7923			       elementSize,rowSize,groupSize,myswapBytes);
7924	   }
7925	   break;
7926	 case GL_SHORT:
7927	   if (depth > 1) {
7928	   halveImage3D(cmpts,extractSshort,shoveSshort,
7929			width,height,depth,
7930			usersImage,dstImage,elementSize,groupSize,rowSize,
7931			imageSize,myswapBytes);
7932	   }
7933	   else {
7934	     halveImage_short(cmpts,width,height,usersImage,dstImage,
7935			      elementSize,rowSize,groupSize,myswapBytes);
7936	   }
7937	   break;
7938	 case GL_UNSIGNED_INT:
7939	   if (depth > 1) {
7940	   halveImage3D(cmpts,extractUint,shoveUint,
7941			width,height,depth,
7942			usersImage,dstImage,elementSize,groupSize,rowSize,
7943			imageSize,myswapBytes);
7944	   }
7945	   else {
7946	     halveImage_uint(cmpts,width,height,usersImage,dstImage,
7947			     elementSize,rowSize,groupSize,myswapBytes);
7948	   }
7949	   break;
7950	 case GL_INT:
7951	   if (depth > 1) {
7952	   halveImage3D(cmpts,extractSint,shoveSint,
7953			width,height,depth,
7954			usersImage,dstImage,elementSize,groupSize,rowSize,
7955			imageSize,myswapBytes);
7956	   }
7957	   else {
7958	     halveImage_int(cmpts,width,height,usersImage,dstImage,
7959			    elementSize,rowSize,groupSize,myswapBytes);
7960	   }
7961	   break;
7962	 case GL_FLOAT:
7963	   if (depth > 1 ) {
7964	   halveImage3D(cmpts,extractFloat,shoveFloat,
7965			width,height,depth,
7966			usersImage,dstImage,elementSize,groupSize,rowSize,
7967			imageSize,myswapBytes);
7968	   }
7969	   else {
7970	     halveImage_float(cmpts,width,height,usersImage,dstImage,
7971			      elementSize,rowSize,groupSize,myswapBytes);
7972	   }
7973	   break;
7974	 case GL_UNSIGNED_BYTE_3_3_2:
7975	   assert(format == GL_RGB);
7976	   halveImagePackedPixel3D(3,extract332,shove332,
7977				   width,height,depth,usersImage,dstImage,
7978				   elementSize,rowSize,imageSize,myswapBytes);
7979	   break;
7980	 case GL_UNSIGNED_BYTE_2_3_3_REV:
7981	   assert(format == GL_RGB);
7982	   halveImagePackedPixel3D(3,extract233rev,shove233rev,
7983				   width,height,depth,usersImage,dstImage,
7984				   elementSize,rowSize,imageSize,myswapBytes);
7985	   break;
7986	 case GL_UNSIGNED_SHORT_5_6_5:
7987	   halveImagePackedPixel3D(3,extract565,shove565,
7988				   width,height,depth,usersImage,dstImage,
7989				   elementSize,rowSize,imageSize,myswapBytes);
7990	   break;
7991	 case GL_UNSIGNED_SHORT_5_6_5_REV:
7992	   halveImagePackedPixel3D(3,extract565rev,shove565rev,
7993				   width,height,depth,usersImage,dstImage,
7994				   elementSize,rowSize,imageSize,myswapBytes);
7995	   break;
7996	 case GL_UNSIGNED_SHORT_4_4_4_4:
7997	   halveImagePackedPixel3D(4,extract4444,shove4444,
7998				   width,height,depth,usersImage,dstImage,
7999				   elementSize,rowSize,imageSize,myswapBytes);
8000	   break;
8001	 case GL_UNSIGNED_SHORT_4_4_4_4_REV:
8002	   halveImagePackedPixel3D(4,extract4444rev,shove4444rev,
8003				   width,height,depth,usersImage,dstImage,
8004				   elementSize,rowSize,imageSize,myswapBytes);
8005	   break;
8006	 case GL_UNSIGNED_SHORT_5_5_5_1:
8007	   halveImagePackedPixel3D(4,extract5551,shove5551,
8008				   width,height,depth,usersImage,dstImage,
8009				   elementSize,rowSize,imageSize,myswapBytes);
8010	   break;
8011	 case GL_UNSIGNED_SHORT_1_5_5_5_REV:
8012	   halveImagePackedPixel3D(4,extract1555rev,shove1555rev,
8013				   width,height,depth,usersImage,dstImage,
8014				   elementSize,rowSize,imageSize,myswapBytes);
8015	   break;
8016	 case GL_UNSIGNED_INT_8_8_8_8:
8017	   halveImagePackedPixel3D(4,extract8888,shove8888,
8018				   width,height,depth,usersImage,dstImage,
8019				   elementSize,rowSize,imageSize,myswapBytes);
8020	   break;
8021	 case GL_UNSIGNED_INT_8_8_8_8_REV:
8022	   halveImagePackedPixel3D(4,extract8888rev,shove8888rev,
8023				   width,height,depth,usersImage,dstImage,
8024				   elementSize,rowSize,imageSize,myswapBytes);
8025	   break;
8026	 case GL_UNSIGNED_INT_10_10_10_2:
8027	   halveImagePackedPixel3D(4,extract1010102,shove1010102,
8028				   width,height,depth,usersImage,dstImage,
8029				   elementSize,rowSize,imageSize,myswapBytes);
8030	   break;
8031	 case GL_UNSIGNED_INT_2_10_10_10_REV:
8032	   halveImagePackedPixel3D(4,extract2101010rev,shove2101010rev,
8033				   width,height,depth,usersImage,dstImage,
8034				   elementSize,rowSize,imageSize,myswapBytes);
8035	   break;
8036	 default:
8037	   assert(0);
8038	   break;
8039	 }
8040       newWidth = width/2;
8041       newHeight = height/2;
8042       newDepth = depth/2;
8043       /* clamp to 1 */
8044       if (newWidth < 1) newWidth= 1;
8045       if (newHeight < 1) newHeight= 1;
8046       if (newDepth < 1) newDepth= 1;
8047
8048       myswapBytes = 0;
8049       rowSize = newWidth * groupSize;
8050       imageSize= rowSize * newHeight; /* 3dstuff */
8051       memReq = imageSize3D(newWidth, newHeight, newDepth, format, type);
8052       /* Swap srcImage and dstImage */
8053       __GLU_SWAP_IMAGE(srcImage,dstImage);
8054       switch(type) {
8055       case GL_UNSIGNED_BYTE:
8056	 dstImage = (GLubyte *)malloc(memReq);
8057	 break;
8058       case GL_BYTE:
8059	 dstImage = (GLbyte *)malloc(memReq);
8060	 break;
8061       case GL_UNSIGNED_SHORT:
8062	 dstImage = (GLushort *)malloc(memReq);
8063	 break;
8064       case GL_SHORT:
8065	 dstImage = (GLshort *)malloc(memReq);
8066	 break;
8067       case GL_UNSIGNED_INT:
8068	 dstImage = (GLuint *)malloc(memReq);
8069	 break;
8070       case GL_INT:
8071	 dstImage = (GLint *)malloc(memReq);
8072	 break;
8073       case GL_FLOAT:
8074	 dstImage = (GLfloat *)malloc(memReq);
8075	 break;
8076       case GL_UNSIGNED_BYTE_3_3_2:
8077       case GL_UNSIGNED_BYTE_2_3_3_REV:
8078	 dstImage = (GLubyte *)malloc(memReq);
8079	 break;
8080       case GL_UNSIGNED_SHORT_5_6_5:
8081       case GL_UNSIGNED_SHORT_5_6_5_REV:
8082       case GL_UNSIGNED_SHORT_4_4_4_4:
8083       case GL_UNSIGNED_SHORT_4_4_4_4_REV:
8084       case GL_UNSIGNED_SHORT_5_5_5_1:
8085       case GL_UNSIGNED_SHORT_1_5_5_5_REV:
8086	 dstImage = (GLushort *)malloc(memReq);
8087	 break;
8088       case GL_UNSIGNED_INT_8_8_8_8:
8089       case GL_UNSIGNED_INT_8_8_8_8_REV:
8090       case GL_UNSIGNED_INT_10_10_10_2:
8091       case GL_UNSIGNED_INT_2_10_10_10_REV:
8092	 dstImage = (GLuint *)malloc(memReq);
8093	 break;
8094       default:
8095	 return GLU_INVALID_ENUM; /* assertion */
8096       }
8097       if (dstImage == NULL) {
8098	 glPixelStorei(GL_UNPACK_ALIGNMENT, psm.unpack_alignment);
8099	 glPixelStorei(GL_UNPACK_SKIP_ROWS, psm.unpack_skip_rows);
8100	 glPixelStorei(GL_UNPACK_SKIP_PIXELS, psm.unpack_skip_pixels);
8101	 glPixelStorei(GL_UNPACK_ROW_LENGTH, psm.unpack_row_length);
8102	 glPixelStorei(GL_UNPACK_SWAP_BYTES, psm.unpack_swap_bytes);
8103	 glPixelStorei(GL_UNPACK_SKIP_IMAGES, psm.unpack_skip_images);
8104	 glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, psm.unpack_image_height);
8105	 free(srcImage);
8106	 return GLU_OUT_OF_MEMORY;
8107       }
8108       /* level userLevel+1 is in srcImage; level userLevel already saved */
8109       level = userLevel+1;
8110   } else {/* user's image is *not* nice power-of-2 sized square */
8111       memReq = imageSize3D(newWidth, newHeight, newDepth, format, type);
8112       switch(type) {
8113	   case GL_UNSIGNED_BYTE:
8114	       dstImage = (GLubyte *)malloc(memReq);
8115	       break;
8116	   case GL_BYTE:
8117	       dstImage = (GLbyte *)malloc(memReq);
8118	       break;
8119	   case GL_UNSIGNED_SHORT:
8120	       dstImage = (GLushort *)malloc(memReq);
8121	       break;
8122	   case GL_SHORT:
8123	       dstImage = (GLshort *)malloc(memReq);
8124	       break;
8125	   case GL_UNSIGNED_INT:
8126	       dstImage = (GLuint *)malloc(memReq);
8127	       break;
8128	   case GL_INT:
8129	       dstImage = (GLint *)malloc(memReq);
8130	       break;
8131	   case GL_FLOAT:
8132	       dstImage = (GLfloat *)malloc(memReq);
8133	       break;
8134	   case GL_UNSIGNED_BYTE_3_3_2:
8135	   case GL_UNSIGNED_BYTE_2_3_3_REV:
8136	       dstImage = (GLubyte *)malloc(memReq);
8137	       break;
8138	   case GL_UNSIGNED_SHORT_5_6_5:
8139	   case GL_UNSIGNED_SHORT_5_6_5_REV:
8140	   case GL_UNSIGNED_SHORT_4_4_4_4:
8141	   case GL_UNSIGNED_SHORT_4_4_4_4_REV:
8142	   case GL_UNSIGNED_SHORT_5_5_5_1:
8143	   case GL_UNSIGNED_SHORT_1_5_5_5_REV:
8144	       dstImage = (GLushort *)malloc(memReq);
8145	       break;
8146	   case GL_UNSIGNED_INT_8_8_8_8:
8147	   case GL_UNSIGNED_INT_8_8_8_8_REV:
8148	   case GL_UNSIGNED_INT_10_10_10_2:
8149	   case GL_UNSIGNED_INT_2_10_10_10_REV:
8150	       dstImage = (GLuint *)malloc(memReq);
8151	       break;
8152	   default:
8153	       return GLU_INVALID_ENUM; /* assertion */
8154       }
8155
8156       if (dstImage == NULL) {
8157	   glPixelStorei(GL_UNPACK_ALIGNMENT, psm.unpack_alignment);
8158	   glPixelStorei(GL_UNPACK_SKIP_ROWS, psm.unpack_skip_rows);
8159	   glPixelStorei(GL_UNPACK_SKIP_PIXELS, psm.unpack_skip_pixels);
8160	   glPixelStorei(GL_UNPACK_ROW_LENGTH, psm.unpack_row_length);
8161	   glPixelStorei(GL_UNPACK_SWAP_BYTES, psm.unpack_swap_bytes);
8162	   glPixelStorei(GL_UNPACK_SKIP_IMAGES, psm.unpack_skip_images);
8163	   glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, psm.unpack_image_height);
8164	   return GLU_OUT_OF_MEMORY;
8165       }
8166       /*printf("Build3DMipmaps(): ScaleImage3D %d %d %d->%d %d %d\n",
8167       width,height,depth,newWidth,newHeight,newDepth);*/
8168
8169       gluScaleImage3D(format, width, height, depth, type, usersImage,
8170		       newWidth, newHeight, newDepth, type, dstImage);
8171
8172       myswapBytes = 0;
8173       rowSize = newWidth * groupSize;
8174       imageSize = rowSize * newHeight; /* 3dstuff */
8175       /* Swap dstImage and srcImage */
8176       __GLU_SWAP_IMAGE(srcImage,dstImage);
8177
8178       if(levels != 0) { /* use as little memory as possible */
8179	 {
8180	    int nextWidth= newWidth/2;
8181	    int nextHeight= newHeight/2;
8182	    int nextDepth= newDepth/2;
8183	    if (nextWidth < 1) nextWidth= 1;
8184	    if (nextHeight < 1) nextHeight= 1;
8185	    if (nextDepth < 1) nextDepth= 1;
8186
8187	 memReq = imageSize3D(nextWidth, nextHeight, nextDepth, format, type);
8188	 }
8189	 switch(type) {
8190	 case GL_UNSIGNED_BYTE:
8191	   dstImage = (GLubyte *)malloc(memReq);
8192	   break;
8193	 case GL_BYTE:
8194	   dstImage = (GLbyte *)malloc(memReq);
8195	   break;
8196	 case GL_UNSIGNED_SHORT:
8197	   dstImage = (GLushort *)malloc(memReq);
8198	   break;
8199	 case GL_SHORT:
8200	   dstImage = (GLshort *)malloc(memReq);
8201	   break;
8202	 case GL_UNSIGNED_INT:
8203	   dstImage = (GLuint *)malloc(memReq);
8204	   break;
8205	 case GL_INT:
8206	   dstImage = (GLint *)malloc(memReq);
8207	   break;
8208	 case GL_FLOAT:
8209	   dstImage = (GLfloat *)malloc(memReq);
8210	   break;
8211	 case GL_UNSIGNED_BYTE_3_3_2:
8212	 case GL_UNSIGNED_BYTE_2_3_3_REV:
8213	   dstImage = (GLubyte *)malloc(memReq);
8214	   break;
8215	 case GL_UNSIGNED_SHORT_5_6_5:
8216	 case GL_UNSIGNED_SHORT_5_6_5_REV:
8217	 case GL_UNSIGNED_SHORT_4_4_4_4:
8218	 case GL_UNSIGNED_SHORT_4_4_4_4_REV:
8219	 case GL_UNSIGNED_SHORT_5_5_5_1:
8220	 case GL_UNSIGNED_SHORT_1_5_5_5_REV:
8221	   dstImage = (GLushort *)malloc(memReq);
8222	   break;
8223	 case GL_UNSIGNED_INT_8_8_8_8:
8224	 case GL_UNSIGNED_INT_8_8_8_8_REV:
8225	 case GL_UNSIGNED_INT_10_10_10_2:
8226	 case GL_UNSIGNED_INT_2_10_10_10_REV:
8227	   dstImage = (GLuint *)malloc(memReq);
8228	   break;
8229	 default:
8230	   return GLU_INVALID_ENUM; /* assertion */
8231	 }
8232	 if (dstImage == NULL) {
8233	   glPixelStorei(GL_UNPACK_ALIGNMENT, psm.unpack_alignment);
8234	   glPixelStorei(GL_UNPACK_SKIP_ROWS, psm.unpack_skip_rows);
8235	   glPixelStorei(GL_UNPACK_SKIP_PIXELS, psm.unpack_skip_pixels);
8236	   glPixelStorei(GL_UNPACK_ROW_LENGTH, psm.unpack_row_length);
8237	   glPixelStorei(GL_UNPACK_SWAP_BYTES, psm.unpack_swap_bytes);
8238	   glPixelStorei(GL_UNPACK_SKIP_IMAGES, psm.unpack_skip_images);
8239	   glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, psm.unpack_image_height);
8240	   free(srcImage);
8241	   return GLU_OUT_OF_MEMORY;
8242	 }
8243       }
8244       /* level userLevel is in srcImage; nothing saved yet */
8245       level = userLevel;
8246   }
8247
8248   glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE);
8249   if (baseLevel <= level && level <= maxLevel) {
8250     gluTexImage3D(target, level, internalFormat, newWidth, newHeight, newDepth,
8251		  0,format, type, (void *)srcImage);
8252   }
8253   level++; /* update current level for the loop */
8254   for (; level <= levels; level++) {
8255       switch(type) {
8256	   case GL_UNSIGNED_BYTE:
8257	       if (newDepth > 1) {
8258	       halveImage3D(cmpts,extractUbyte,shoveUbyte,
8259			    newWidth,newHeight,newDepth,
8260			    srcImage,dstImage,elementSize,groupSize,rowSize,
8261			    imageSize,myswapBytes);
8262	       }
8263	       else {
8264		 halveImage_ubyte(cmpts,newWidth,newHeight,srcImage,dstImage,
8265				  elementSize,rowSize,groupSize);
8266	       }
8267	       break;
8268	   case GL_BYTE:
8269	       if (newDepth > 1) {
8270	       halveImage3D(cmpts,extractSbyte,shoveSbyte,
8271			    newWidth,newHeight,newDepth,
8272			    srcImage,dstImage,elementSize,groupSize,rowSize,
8273			    imageSize,myswapBytes);
8274	       }
8275	       else {
8276		 halveImage_byte(cmpts,newWidth,newHeight,srcImage,dstImage,
8277				  elementSize,rowSize,groupSize);
8278	       }
8279	       break;
8280	   case GL_UNSIGNED_SHORT:
8281	       if (newDepth > 1) {
8282	       halveImage3D(cmpts,extractUshort,shoveUshort,
8283			    newWidth,newHeight,newDepth,
8284			    srcImage,dstImage,elementSize,groupSize,rowSize,
8285			    imageSize,myswapBytes);
8286	       }
8287	       else {
8288		 halveImage_ushort(cmpts,newWidth,newHeight,srcImage,dstImage,
8289				   elementSize,rowSize,groupSize,myswapBytes);
8290	       }
8291	       break;
8292	   case GL_SHORT:
8293	       if (newDepth > 1) {
8294	       halveImage3D(cmpts,extractSshort,shoveSshort,
8295			    newWidth,newHeight,newDepth,
8296			    srcImage,dstImage,elementSize,groupSize,rowSize,
8297			    imageSize,myswapBytes);
8298	       }
8299	       else {
8300		 halveImage_short(cmpts,newWidth,newHeight,srcImage,dstImage,
8301				  elementSize,rowSize,groupSize,myswapBytes);
8302	       }
8303	       break;
8304	   case GL_UNSIGNED_INT:
8305	       if (newDepth > 1) {
8306	       halveImage3D(cmpts,extractUint,shoveUint,
8307			    newWidth,newHeight,newDepth,
8308			    srcImage,dstImage,elementSize,groupSize,rowSize,
8309			    imageSize,myswapBytes);
8310	       }
8311	       else {
8312		 halveImage_uint(cmpts,newWidth,newHeight,srcImage,dstImage,
8313				 elementSize,rowSize,groupSize,myswapBytes);
8314	       }
8315	       break;
8316	   case GL_INT:
8317	       if (newDepth > 1) {
8318	       halveImage3D(cmpts,extractSint,shoveSint,
8319			    newWidth,newHeight,newDepth,
8320			    srcImage,dstImage,elementSize,groupSize,rowSize,
8321			    imageSize,myswapBytes);
8322	       }
8323	       else {
8324		 halveImage_int(cmpts,newWidth,newHeight,srcImage,dstImage,
8325				elementSize,rowSize,groupSize,myswapBytes);
8326	       }
8327	       break;
8328	   case GL_FLOAT:
8329	       if (newDepth > 1) {
8330	       halveImage3D(cmpts,extractFloat,shoveFloat,
8331			    newWidth,newHeight,newDepth,
8332			    srcImage,dstImage,elementSize,groupSize,rowSize,
8333			    imageSize,myswapBytes);
8334	       }
8335	       else {
8336		 halveImage_float(cmpts,newWidth,newHeight,srcImage,dstImage,
8337				  elementSize,rowSize,groupSize,myswapBytes);
8338	       }
8339	       break;
8340	   case GL_UNSIGNED_BYTE_3_3_2:
8341	       halveImagePackedPixel3D(3,extract332,shove332,
8342				       newWidth,newHeight,newDepth,
8343				       srcImage,dstImage,elementSize,rowSize,
8344				       imageSize,myswapBytes);
8345	       break;
8346	   case GL_UNSIGNED_BYTE_2_3_3_REV:
8347	       halveImagePackedPixel3D(3,extract233rev,shove233rev,
8348				       newWidth,newHeight,newDepth,
8349				       srcImage,dstImage,elementSize,rowSize,
8350				       imageSize,myswapBytes);
8351	       break;
8352	   case GL_UNSIGNED_SHORT_5_6_5:
8353	       halveImagePackedPixel3D(3,extract565,shove565,
8354				       newWidth,newHeight,newDepth,
8355				       srcImage,dstImage,elementSize,rowSize,
8356				       imageSize,myswapBytes);
8357	       break;
8358	   case GL_UNSIGNED_SHORT_5_6_5_REV:
8359	       halveImagePackedPixel3D(3,extract565rev,shove565rev,
8360				       newWidth,newHeight,newDepth,
8361				       srcImage,dstImage,elementSize,rowSize,
8362				       imageSize,myswapBytes);
8363	       break;
8364	   case GL_UNSIGNED_SHORT_4_4_4_4:
8365	       halveImagePackedPixel3D(4,extract4444,shove4444,
8366				       newWidth,newHeight,newDepth,
8367				       srcImage,dstImage,elementSize,rowSize,
8368				       imageSize,myswapBytes);
8369	       break;
8370	   case GL_UNSIGNED_SHORT_4_4_4_4_REV:
8371	       halveImagePackedPixel3D(4,extract4444rev,shove4444rev,
8372				       newWidth,newHeight,newDepth,
8373				       srcImage,dstImage,elementSize,rowSize,
8374				       imageSize,myswapBytes);
8375	       break;
8376	   case GL_UNSIGNED_SHORT_5_5_5_1:
8377	       halveImagePackedPixel3D(4,extract5551,shove5551,
8378				       newWidth,newHeight,newDepth,
8379				       srcImage,dstImage,elementSize,rowSize,
8380				       imageSize,myswapBytes);
8381	       break;
8382	   case GL_UNSIGNED_SHORT_1_5_5_5_REV:
8383	       halveImagePackedPixel3D(4,extract1555rev,shove1555rev,
8384				       newWidth,newHeight,newDepth,
8385				       srcImage,dstImage,elementSize,rowSize,
8386				       imageSize,myswapBytes);
8387	       break;
8388	   case GL_UNSIGNED_INT_8_8_8_8:
8389	       halveImagePackedPixel3D(4,extract8888,shove8888,
8390				       newWidth,newHeight,newDepth,
8391				       srcImage,dstImage,elementSize,rowSize,
8392				       imageSize,myswapBytes);
8393	       break;
8394	   case GL_UNSIGNED_INT_8_8_8_8_REV:
8395	       halveImagePackedPixel3D(4,extract8888rev,shove8888rev,
8396				       newWidth,newHeight,newDepth,
8397				       srcImage,dstImage,elementSize,rowSize,
8398				       imageSize,myswapBytes);
8399	       break;
8400	   case GL_UNSIGNED_INT_10_10_10_2:
8401	       halveImagePackedPixel3D(4,extract1010102,shove1010102,
8402				       newWidth,newHeight,newDepth,
8403				       srcImage,dstImage,elementSize,rowSize,
8404				       imageSize,myswapBytes);
8405	       break;
8406	   case GL_UNSIGNED_INT_2_10_10_10_REV:
8407	       halveImagePackedPixel3D(4,extract2101010rev,shove2101010rev,
8408				       newWidth,newHeight,newDepth,
8409				       srcImage,dstImage,elementSize,rowSize,
8410				       imageSize,myswapBytes);
8411	       break;
8412	   default:
8413	       assert(0);
8414	       break;
8415       }
8416
8417       __GLU_SWAP_IMAGE(srcImage,dstImage);
8418
8419       if (newWidth > 1) { newWidth /= 2; rowSize /= 2;}
8420       if (newHeight > 1) { newHeight /= 2; imageSize = rowSize * newHeight; }
8421       if (newDepth > 1) newDepth /= 2;
8422       {
8423	  /* call tex image with srcImage untouched since it's not padded */
8424	  if (baseLevel <= level && level <= maxLevel) {
8425	    gluTexImage3D(target, level, internalFormat, newWidth, newHeight,
8426			 newDepth,0, format, type, (void *) srcImage);
8427	  }
8428       }
8429   } /* for level */
8430   glPixelStorei(GL_UNPACK_ALIGNMENT, psm.unpack_alignment);
8431   glPixelStorei(GL_UNPACK_SKIP_ROWS, psm.unpack_skip_rows);
8432   glPixelStorei(GL_UNPACK_SKIP_PIXELS, psm.unpack_skip_pixels);
8433   glPixelStorei(GL_UNPACK_ROW_LENGTH, psm.unpack_row_length);
8434   glPixelStorei(GL_UNPACK_SWAP_BYTES, psm.unpack_swap_bytes);
8435   glPixelStorei(GL_UNPACK_SKIP_IMAGES, psm.unpack_skip_images);
8436   glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, psm.unpack_image_height);
8437
8438   free(srcImage); /*if you get to here, a srcImage has always been malloc'ed*/
8439   if (dstImage) { /* if it's non-rectangular and only 1 level */
8440     free(dstImage);
8441   }
8442   return 0;
8443} /* gluBuild3DMipmapLevelsCore() */
8444
8445GLint GLAPIENTRY
8446gluBuild3DMipmapLevels(GLenum target, GLint internalFormat,
8447			     GLsizei width, GLsizei height, GLsizei depth,
8448			     GLenum format, GLenum type,
8449			     GLint userLevel, GLint baseLevel, GLint maxLevel,
8450			     const void *data)
8451{
8452   int level, levels;
8453
8454   int rc= checkMipmapArgs(internalFormat,format,type);
8455   if (rc != 0) return rc;
8456
8457   if (width < 1 || height < 1 || depth < 1) {
8458       return GLU_INVALID_VALUE;
8459   }
8460
8461   if(type == GL_BITMAP) {
8462      return GLU_INVALID_ENUM;
8463   }
8464
8465   levels = computeLog(width);
8466   level = computeLog(height);
8467   if (level > levels) levels=level;
8468   level = computeLog(depth);
8469   if (level > levels) levels=level;
8470
8471   levels+= userLevel;
8472   if (!isLegalLevels(userLevel,baseLevel,maxLevel,levels))
8473      return GLU_INVALID_VALUE;
8474
8475   return gluBuild3DMipmapLevelsCore(target, internalFormat,
8476				     width, height, depth,
8477				     width, height, depth,
8478				     format, type,
8479				     userLevel, baseLevel, maxLevel,
8480				     data);
8481} /* gluBuild3DMipmapLevels() */
8482
8483GLint GLAPIENTRY
8484gluBuild3DMipmaps(GLenum target, GLint internalFormat,
8485			GLsizei width, GLsizei height, GLsizei depth,
8486			GLenum format, GLenum type, const void *data)
8487{
8488   GLint widthPowerOf2, heightPowerOf2, depthPowerOf2;
8489   int level, levels;
8490
8491   int rc= checkMipmapArgs(internalFormat,format,type);
8492   if (rc != 0) return rc;
8493
8494   if (width < 1 || height < 1 || depth < 1) {
8495       return GLU_INVALID_VALUE;
8496   }
8497
8498   if(type == GL_BITMAP) {
8499      return GLU_INVALID_ENUM;
8500   }
8501
8502   closestFit3D(target,width,height,depth,internalFormat,format,type,
8503		&widthPowerOf2,&heightPowerOf2,&depthPowerOf2);
8504
8505   levels = computeLog(widthPowerOf2);
8506   level = computeLog(heightPowerOf2);
8507   if (level > levels) levels=level;
8508   level = computeLog(depthPowerOf2);
8509   if (level > levels) levels=level;
8510
8511   return gluBuild3DMipmapLevelsCore(target, internalFormat,
8512				     width, height, depth,
8513				     widthPowerOf2, heightPowerOf2,
8514				     depthPowerOf2,
8515				     format, type, 0, 0, levels,
8516				     data);
8517} /* gluBuild3DMipmaps() */
8518
8519static GLdouble extractUbyte(int isSwap, const void *ubyte)
8520{
8521   isSwap= isSwap;		/* turn off warnings */
8522
8523   assert(*((const GLubyte *)ubyte) <= 255);
8524
8525   return (GLdouble)(*((const GLubyte *)ubyte));
8526} /* extractUbyte() */
8527
8528static void shoveUbyte(GLdouble value, int index, void *data)
8529{
8530   assert(0.0 <= value && value < 256.0);
8531
8532   ((GLubyte *)data)[index]= (GLubyte)value;
8533} /* shoveUbyte() */
8534
8535static GLdouble extractSbyte(int isSwap, const void *sbyte)
8536{
8537   isSwap= isSwap;		/* turn off warnings */
8538
8539   assert(*((const GLbyte *)sbyte) <= 127);
8540
8541   return (GLdouble)(*((const GLbyte *)sbyte));
8542} /* extractSbyte() */
8543
8544static void shoveSbyte(GLdouble value, int index, void *data)
8545{
8546   ((GLbyte *)data)[index]= (GLbyte)value;
8547} /* shoveSbyte() */
8548
8549static GLdouble extractUshort(int isSwap, const void *uitem)
8550{
8551   GLushort ushort;
8552
8553   if (isSwap) {
8554     ushort= __GLU_SWAP_2_BYTES(uitem);
8555   }
8556   else {
8557     ushort= *(const GLushort *)uitem;
8558   }
8559
8560   assert(ushort <= 65535);
8561
8562   return (GLdouble)ushort;
8563} /* extractUshort() */
8564
8565static void shoveUshort(GLdouble value, int index, void *data)
8566{
8567   assert(0.0 <= value && value < 65536.0);
8568
8569   ((GLushort *)data)[index]= (GLushort)value;
8570} /* shoveUshort() */
8571
8572static GLdouble extractSshort(int isSwap, const void *sitem)
8573{
8574   GLshort sshort;
8575
8576   if (isSwap) {
8577     sshort= __GLU_SWAP_2_BYTES(sitem);
8578   }
8579   else {
8580     sshort= *(const GLshort *)sitem;
8581   }
8582
8583   assert(sshort <= 32767);
8584
8585   return (GLdouble)sshort;
8586} /* extractSshort() */
8587
8588static void shoveSshort(GLdouble value, int index, void *data)
8589{
8590   assert(0.0 <= value && value < 32768.0);
8591
8592   ((GLshort *)data)[index]= (GLshort)value;
8593} /* shoveSshort() */
8594
8595static GLdouble extractUint(int isSwap, const void *uitem)
8596{
8597   GLuint uint;
8598
8599   if (isSwap) {
8600     uint= __GLU_SWAP_4_BYTES(uitem);
8601   }
8602   else {
8603     uint= *(const GLuint *)uitem;
8604   }
8605
8606   assert(uint <= 0xffffffff);
8607
8608   return (GLdouble)uint;
8609} /* extractUint() */
8610
8611static void shoveUint(GLdouble value, int index, void *data)
8612{
8613   assert(0.0 <= value && value <= (GLdouble) UINT_MAX);
8614
8615   ((GLuint *)data)[index]= (GLuint)value;
8616} /* shoveUint() */
8617
8618static GLdouble extractSint(int isSwap, const void *sitem)
8619{
8620   GLint sint;
8621
8622   if (isSwap) {
8623     sint= __GLU_SWAP_4_BYTES(sitem);
8624   }
8625   else {
8626     sint= *(const GLint *)sitem;
8627   }
8628
8629   assert(sint <= 0x7fffffff);
8630
8631   return (GLdouble)sint;
8632} /* extractSint() */
8633
8634static void shoveSint(GLdouble value, int index, void *data)
8635{
8636   assert(0.0 <= value && value <= (GLdouble) INT_MAX);
8637
8638   ((GLint *)data)[index]= (GLint)value;
8639} /* shoveSint() */
8640
8641static GLdouble extractFloat(int isSwap, const void *item)
8642{
8643   GLfloat ffloat;
8644
8645   if (isSwap) {
8646     ffloat= __GLU_SWAP_4_BYTES(item);
8647   }
8648   else {
8649     ffloat= *(const GLfloat *)item;
8650   }
8651
8652   assert(ffloat <= 1.0);
8653
8654   return (GLdouble)ffloat;
8655} /* extractFloat() */
8656
8657static void shoveFloat(GLdouble value, int index, void *data)
8658{
8659   assert(0.0 <= value && value <= 1.0);
8660
8661   ((GLfloat *)data)[index]= value;
8662} /* shoveFloat() */
8663
8664static void halveImageSlice(int components,
8665			    GLdouble (*extract)(int, const void *),
8666			    void (*shove)(GLdouble, int, void *),
8667			    GLint width, GLint height, GLint depth,
8668			    const void *dataIn, void *dataOut,
8669			    GLint elementSizeInBytes,
8670			    GLint groupSizeInBytes,
8671			    GLint rowSizeInBytes,
8672			    GLint imageSizeInBytes,
8673			    GLint isSwap)
8674{
8675   int ii, jj;
8676   int halfWidth= width / 2;
8677   int halfHeight= height / 2;
8678   int halfDepth= depth / 2;
8679   const char *src= (const char *)dataIn;
8680   int rowPadBytes= rowSizeInBytes - (width * groupSizeInBytes);
8681   int imagePadBytes= imageSizeInBytes - (width*height*groupSizeInBytes);
8682   int outIndex= 0;
8683
8684   assert((width == 1 || height == 1) && depth >= 2);
8685
8686   if (width == height) {	/* a 1-pixel column viewed from top */
8687      /* printf("1-column\n");*/
8688      assert(width == 1 && height == 1);
8689      assert(depth >= 2);
8690
8691      for (ii= 0; ii< halfDepth; ii++) {
8692	 int cc;
8693
8694	 for (cc = 0; cc < components; cc++) {
8695	    double totals[4];
8696	    double extractTotals[BOX2][4];
8697	    int kk;
8698
8699	    extractTotals[0][cc]= (*extract)(isSwap,src);
8700	    extractTotals[1][cc]= (*extract)(isSwap,(src+imageSizeInBytes));
8701
8702	    /* average 2 pixels since only a column */
8703	    totals[cc]= 0.0;
8704	    /* totals[RED]= extractTotals[0][RED]+extractTotals[1][RED];
8705	     * totals[RED]/= 2.0;
8706	     */
8707	    for (kk = 0; kk < BOX2; kk++) {
8708	      totals[cc]+= extractTotals[kk][cc];
8709	    }
8710	    totals[cc]/= (double)BOX2;
8711
8712	    (*shove)(totals[cc],outIndex,dataOut);
8713	    outIndex++;
8714	    src+= elementSizeInBytes;
8715	 } /* for cc */
8716
8717	 /* skip over to next group of 2 */
8718	 src+= rowSizeInBytes;
8719      } /* for ii */
8720
8721      assert(src == &((const char *)dataIn)[rowSizeInBytes*height*depth]);
8722      assert(outIndex == halfDepth * components);
8723   }
8724   else if (height == 1) {	/* horizontal slice viewed from top */
8725      /* printf("horizontal slice\n"); */
8726      assert(width != 1);
8727
8728      for (ii= 0; ii< halfDepth; ii++) {
8729	 for (jj= 0; jj< halfWidth; jj++) {
8730	    int cc;
8731
8732	    for (cc = 0; cc < components; cc++) {
8733	       int kk;
8734	       double totals[4];
8735	       double extractTotals[BOX4][4];
8736
8737	       extractTotals[0][cc]=(*extract)(isSwap,src);
8738	       extractTotals[1][cc]=(*extract)(isSwap,
8739					       (src+groupSizeInBytes));
8740	       extractTotals[2][cc]=(*extract)(isSwap,
8741					       (src+imageSizeInBytes));
8742	       extractTotals[3][cc]=(*extract)(isSwap,
8743					       (src+imageSizeInBytes+groupSizeInBytes));
8744
8745	       /* grab 4 pixels to average */
8746	       totals[cc]= 0.0;
8747	       /* totals[RED]= extractTotals[0][RED]+extractTotals[1][RED]+
8748		*	       extractTotals[2][RED]+extractTotals[3][RED];
8749		* totals[RED]/= 4.0;
8750		*/
8751	       for (kk = 0; kk < BOX4; kk++) {
8752		  totals[cc]+= extractTotals[kk][cc];
8753	       }
8754	       totals[cc]/= (double)BOX4;
8755
8756	       (*shove)(totals[cc],outIndex,dataOut);
8757	       outIndex++;
8758
8759	       src+= elementSizeInBytes;
8760	    } /* for cc */
8761
8762	    /* skip over to next horizontal square of 4 */
8763	    src+= groupSizeInBytes;
8764	 } /* for jj */
8765	 src+= rowPadBytes;
8766
8767	 src+= rowSizeInBytes;
8768      } /* for ii */
8769
8770      assert(src == &((const char *)dataIn)[rowSizeInBytes*height*depth]);
8771      assert(outIndex == halfWidth * halfDepth * components);
8772   }
8773   else if (width == 1) {	/* vertical slice viewed from top */
8774      /* printf("vertical slice\n"); */
8775      assert(height != 1);
8776
8777      for (ii= 0; ii< halfDepth; ii++) {
8778	 for (jj= 0; jj< halfHeight; jj++) {
8779	    int cc;
8780
8781	    for (cc = 0; cc < components; cc++) {
8782	       int kk;
8783	       double totals[4];
8784	       double extractTotals[BOX4][4];
8785
8786	       extractTotals[0][cc]=(*extract)(isSwap,src);
8787	       extractTotals[1][cc]=(*extract)(isSwap,
8788					       (src+rowSizeInBytes));
8789	       extractTotals[2][cc]=(*extract)(isSwap,
8790					       (src+imageSizeInBytes));
8791	       extractTotals[3][cc]=(*extract)(isSwap,
8792					       (src+imageSizeInBytes+rowSizeInBytes));
8793
8794	       /* grab 4 pixels to average */
8795	       totals[cc]= 0.0;
8796	       /* totals[RED]= extractTotals[0][RED]+extractTotals[1][RED]+
8797		*	       extractTotals[2][RED]+extractTotals[3][RED];
8798		* totals[RED]/= 4.0;
8799		*/
8800	       for (kk = 0; kk < BOX4; kk++) {
8801		  totals[cc]+= extractTotals[kk][cc];
8802	       }
8803	       totals[cc]/= (double)BOX4;
8804
8805	       (*shove)(totals[cc],outIndex,dataOut);
8806	       outIndex++;
8807
8808	       src+= elementSizeInBytes;
8809	    } /* for cc */
8810	    src+= rowPadBytes;
8811
8812	    /* skip over to next vertical square of 4 */
8813	    src+= rowSizeInBytes;
8814	 } /* for jj */
8815         src+= imagePadBytes;
8816
8817	 src+= imageSizeInBytes;
8818      } /* for ii */
8819
8820      assert(src == &((const char *)dataIn)[rowSizeInBytes*height*depth]);
8821      assert(outIndex == halfHeight * halfDepth * components);
8822   }
8823
8824} /* halveImageSlice() */
8825
8826static void halveImage3D(int components,
8827			 GLdouble (*extract)(int, const void *),
8828			 void (*shove)(GLdouble, int, void *),
8829			 GLint width, GLint height, GLint depth,
8830			 const void *dataIn, void *dataOut,
8831			 GLint elementSizeInBytes,
8832			 GLint groupSizeInBytes,
8833			 GLint rowSizeInBytes,
8834			 GLint imageSizeInBytes,
8835			 GLint isSwap)
8836{
8837   assert(depth > 1);
8838
8839   /* a horizontal/vertical/one-column slice viewed from top */
8840   if (width == 1 || height == 1) {
8841      assert(1 <= depth);
8842
8843      halveImageSlice(components,extract,shove, width, height, depth,
8844		      dataIn, dataOut, elementSizeInBytes, groupSizeInBytes,
8845		      rowSizeInBytes, imageSizeInBytes, isSwap);
8846      return;
8847   }
8848   {
8849      int ii, jj, dd;
8850
8851      int halfWidth= width / 2;
8852      int halfHeight= height / 2;
8853      int halfDepth= depth / 2;
8854      const char *src= (const char *) dataIn;
8855      int rowPadBytes= rowSizeInBytes - (width*groupSizeInBytes);
8856      int imagePadBytes= imageSizeInBytes - (width*height*groupSizeInBytes);
8857      int outIndex= 0;
8858
8859      for (dd= 0; dd < halfDepth; dd++) {
8860	 for (ii= 0; ii< halfHeight; ii++) {
8861	    for (jj= 0; jj< halfWidth; jj++) {
8862	       int cc;
8863
8864	       for (cc= 0; cc < components; cc++) {
8865		  int kk;
8866#define BOX8 8
8867		  double totals[4];	/* 4 is maximum components */
8868		  double extractTotals[BOX8][4]; /* 4 is maximum components */
8869
8870		  extractTotals[0][cc]= (*extract)(isSwap,src);
8871		  extractTotals[1][cc]= (*extract)(isSwap,
8872						   (src+groupSizeInBytes));
8873		  extractTotals[2][cc]= (*extract)(isSwap,
8874						   (src+rowSizeInBytes));
8875		  extractTotals[3][cc]= (*extract)(isSwap,
8876						   (src+rowSizeInBytes+groupSizeInBytes));
8877
8878		  extractTotals[4][cc]= (*extract)(isSwap,
8879						   (src+imageSizeInBytes));
8880
8881		  extractTotals[5][cc]= (*extract)(isSwap,
8882						   (src+groupSizeInBytes+imageSizeInBytes));
8883		  extractTotals[6][cc]= (*extract)(isSwap,
8884						   (src+rowSizeInBytes+imageSizeInBytes));
8885		  extractTotals[7][cc]= (*extract)(isSwap,
8886						   (src+rowSizeInBytes+groupSizeInBytes+imageSizeInBytes));
8887
8888		  totals[cc]= 0.0;
8889
8890		  /* totals[RED]= extractTotals[0][RED]+extractTotals[1][RED]+
8891		   *		  extractTotals[2][RED]+extractTotals[3][RED]+
8892		   *		  extractTotals[4][RED]+extractTotals[5][RED]+
8893		   *		  extractTotals[6][RED]+extractTotals[7][RED];
8894		   * totals[RED]/= 8.0;
8895		   */
8896		  for (kk = 0; kk < BOX8; kk++) {
8897		     totals[cc]+= extractTotals[kk][cc];
8898		  }
8899		  totals[cc]/= (double)BOX8;
8900
8901		  (*shove)(totals[cc],outIndex,dataOut);
8902
8903		  outIndex++;
8904
8905		  src+= elementSizeInBytes; /* go to next component */
8906	       } /* for cc */
8907
8908	       /* skip over to next square of 4 */
8909	       src+= groupSizeInBytes;
8910	    } /* for jj */
8911	    /* skip past pad bytes, if any, to get to next row */
8912	    src+= rowPadBytes;
8913
8914	    /* src is at beginning of a row here, but it's the second row of
8915	     * the square block of 4 pixels that we just worked on so we
8916	     * need to go one more row.
8917	     * i.e.,
8918	     *			 OO...
8919	     *		 here -->OO...
8920	     *	     but want -->OO...
8921	     *			 OO...
8922	     *			 ...
8923	     */
8924	    src+= rowSizeInBytes;
8925	 } /* for ii */
8926
8927	 /* skip past pad bytes, if any, to get to next image */
8928	 src+= imagePadBytes;
8929
8930	 src+= imageSizeInBytes;
8931      } /* for dd */
8932
8933      /* both pointers must reach one byte after the end */
8934      assert(src == &((const char *)dataIn)[rowSizeInBytes*height*depth]);
8935      assert(outIndex == halfWidth * halfHeight * halfDepth * components);
8936   }
8937} /* halveImage3D() */
8938
8939
8940
8941/*** mipmap.c ***/
8942
8943