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