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