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