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