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