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