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