glu/sgi: Fix memory leak in bitmapBuild2DMipmaps.
[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 free(beforeImage);
3530 free(afterImage);
3531 return GLU_OUT_OF_MEMORY;
3532 }
3533
3534 retrieveStoreModes(&psm);
3535 fill_image(&psm,widthin, heightin, format, typein, is_index(format),
3536 datain, beforeImage);
3537 components = elements_per_group(format, 0);
3538 scale_internal(components, widthin, heightin, beforeImage,
3539 widthout, heightout, afterImage);
3540 empty_image(&psm,widthout, heightout, format, typeout,
3541 is_index(format), afterImage, dataout);
3542 free((GLbyte *) beforeImage);
3543 free((GLbyte *) afterImage);
3544
3545 return 0;
3546 }
3547
3548 int gluBuild1DMipmapLevelsCore(GLenum target, GLint internalFormat,
3549 GLsizei width,
3550 GLsizei widthPowerOf2,
3551 GLenum format, GLenum type,
3552 GLint userLevel, GLint baseLevel,GLint maxLevel,
3553 const void *data)
3554 {
3555 GLint newwidth;
3556 GLint level, levels;
3557 GLushort *newImage;
3558 GLint newImage_width;
3559 GLushort *otherImage;
3560 GLushort *imageTemp;
3561 GLint memreq;
3562 GLint cmpts;
3563 PixelStorageModes psm;
3564
3565 assert(checkMipmapArgs(internalFormat,format,type) == 0);
3566 assert(width >= 1);
3567
3568 otherImage = NULL;
3569
3570 newwidth= widthPowerOf2;
3571 levels = computeLog(newwidth);
3572
3573 levels+= userLevel;
3574
3575 retrieveStoreModes(&psm);
3576 newImage = (GLushort *)
3577 malloc(image_size(width, 1, format, GL_UNSIGNED_SHORT));
3578 newImage_width = width;
3579 if (newImage == NULL) {
3580 return GLU_OUT_OF_MEMORY;
3581 }
3582 fill_image(&psm,width, 1, format, type, is_index(format),
3583 data, newImage);
3584 cmpts = elements_per_group(format,type);
3585 glPixelStorei(GL_UNPACK_ALIGNMENT, 2);
3586 glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
3587 glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
3588 glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
3589 /*
3590 ** If swap_bytes was set, swapping occurred in fill_image.
3591 */
3592 glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE);
3593
3594 for (level = userLevel; level <= levels; level++) {
3595 if (newImage_width == newwidth) {
3596 /* Use newImage for this level */
3597 if (baseLevel <= level && level <= maxLevel) {
3598 glTexImage1D(target, level, internalFormat, newImage_width,
3599 0, format, GL_UNSIGNED_SHORT, (void *) newImage);
3600 }
3601 } else {
3602 if (otherImage == NULL) {
3603 memreq = image_size(newwidth, 1, format, GL_UNSIGNED_SHORT);
3604 otherImage = (GLushort *) malloc(memreq);
3605 if (otherImage == NULL) {
3606 glPixelStorei(GL_UNPACK_ALIGNMENT, psm.unpack_alignment);
3607 glPixelStorei(GL_UNPACK_SKIP_ROWS, psm.unpack_skip_rows);
3608 glPixelStorei(GL_UNPACK_SKIP_PIXELS,psm.unpack_skip_pixels);
3609 glPixelStorei(GL_UNPACK_ROW_LENGTH, psm.unpack_row_length);
3610 glPixelStorei(GL_UNPACK_SWAP_BYTES, psm.unpack_swap_bytes);
3611 return GLU_OUT_OF_MEMORY;
3612 }
3613 }
3614 scale_internal(cmpts, newImage_width, 1, newImage,
3615 newwidth, 1, otherImage);
3616 /* Swap newImage and otherImage */
3617 imageTemp = otherImage;
3618 otherImage = newImage;
3619 newImage = imageTemp;
3620
3621 newImage_width = newwidth;
3622 if (baseLevel <= level && level <= maxLevel) {
3623 glTexImage1D(target, level, internalFormat, newImage_width,
3624 0, format, GL_UNSIGNED_SHORT, (void *) newImage);
3625 }
3626 }
3627 if (newwidth > 1) newwidth /= 2;
3628 }
3629 glPixelStorei(GL_UNPACK_ALIGNMENT, psm.unpack_alignment);
3630 glPixelStorei(GL_UNPACK_SKIP_ROWS, psm.unpack_skip_rows);
3631 glPixelStorei(GL_UNPACK_SKIP_PIXELS, psm.unpack_skip_pixels);
3632 glPixelStorei(GL_UNPACK_ROW_LENGTH, psm.unpack_row_length);
3633 glPixelStorei(GL_UNPACK_SWAP_BYTES, psm.unpack_swap_bytes);
3634
3635 free((GLbyte *) newImage);
3636 if (otherImage) {
3637 free((GLbyte *) otherImage);
3638 }
3639 return 0;
3640 }
3641
3642 GLint GLAPIENTRY
3643 gluBuild1DMipmapLevels(GLenum target, GLint internalFormat,
3644 GLsizei width,
3645 GLenum format, GLenum type,
3646 GLint userLevel, GLint baseLevel, GLint maxLevel,
3647 const void *data)
3648 {
3649 int levels;
3650
3651 int rc= checkMipmapArgs(internalFormat,format,type);
3652 if (rc != 0) return rc;
3653
3654 if (width < 1) {
3655 return GLU_INVALID_VALUE;
3656 }
3657
3658 levels = computeLog(width);
3659
3660 levels+= userLevel;
3661 if (!isLegalLevels(userLevel,baseLevel,maxLevel,levels))
3662 return GLU_INVALID_VALUE;
3663
3664 return gluBuild1DMipmapLevelsCore(target, internalFormat,
3665 width,
3666 width,format, type,
3667 userLevel, baseLevel, maxLevel,
3668 data);
3669 } /* gluBuild1DMipmapLevels() */
3670
3671 GLint GLAPIENTRY
3672 gluBuild1DMipmaps(GLenum target, GLint internalFormat, GLsizei width,
3673 GLenum format, GLenum type,
3674 const void *data)
3675 {
3676 GLint widthPowerOf2;
3677 int levels;
3678 GLint dummy;
3679
3680 int rc= checkMipmapArgs(internalFormat,format,type);
3681 if (rc != 0) return rc;
3682
3683 if (width < 1) {
3684 return GLU_INVALID_VALUE;
3685 }
3686
3687 closestFit(target,width,1,internalFormat,format,type,&widthPowerOf2,&dummy);
3688 levels = computeLog(widthPowerOf2);
3689
3690 return gluBuild1DMipmapLevelsCore(target,internalFormat,
3691 width,
3692 widthPowerOf2,
3693 format,type,0,0,levels,data);
3694 }
3695
3696 static int bitmapBuild2DMipmaps(GLenum target, GLint internalFormat,
3697 GLint width, GLint height, GLenum format,
3698 GLenum type, const void *data)
3699 {
3700 GLint newwidth, newheight;
3701 GLint level, levels;
3702 GLushort *newImage;
3703 GLint newImage_width;
3704 GLint newImage_height;
3705 GLushort *otherImage;
3706 GLushort *imageTemp;
3707 GLint memreq;
3708 GLint cmpts;
3709 PixelStorageModes psm;
3710
3711 retrieveStoreModes(&psm);
3712
3713 #if 0
3714 glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxsize);
3715 newwidth = nearestPower(width);
3716 if (newwidth > maxsize) newwidth = maxsize;
3717 newheight = nearestPower(height);
3718 if (newheight > maxsize) newheight = maxsize;
3719 #else
3720 closestFit(target,width,height,internalFormat,format,type,
3721 &newwidth,&newheight);
3722 #endif
3723 levels = computeLog(newwidth);
3724 level = computeLog(newheight);
3725 if (level > levels) levels=level;
3726
3727 otherImage = NULL;
3728 newImage = (GLushort *)
3729 malloc(image_size(width, height, format, GL_UNSIGNED_SHORT));
3730 newImage_width = width;
3731 newImage_height = height;
3732 if (newImage == NULL) {
3733 return GLU_OUT_OF_MEMORY;
3734 }
3735
3736 fill_image(&psm,width, height, format, type, is_index(format),
3737 data, newImage);
3738
3739 cmpts = elements_per_group(format,type);
3740 glPixelStorei(GL_UNPACK_ALIGNMENT, 2);
3741 glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
3742 glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
3743 glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
3744 /*
3745 ** If swap_bytes was set, swapping occurred in fill_image.
3746 */
3747 glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE);
3748
3749 for (level = 0; level <= levels; level++) {
3750 if (newImage_width == newwidth && newImage_height == newheight) { /* Use newImage for this level */
3751 glTexImage2D(target, level, internalFormat, newImage_width,
3752 newImage_height, 0, format, GL_UNSIGNED_SHORT,
3753 (void *) newImage);
3754 } else {
3755 if (otherImage == NULL) {
3756 memreq =
3757 image_size(newwidth, newheight, format, GL_UNSIGNED_SHORT);
3758 otherImage = (GLushort *) malloc(memreq);
3759 if (otherImage == NULL) {
3760 glPixelStorei(GL_UNPACK_ALIGNMENT, psm.unpack_alignment);
3761 glPixelStorei(GL_UNPACK_SKIP_ROWS, psm.unpack_skip_rows);
3762 glPixelStorei(GL_UNPACK_SKIP_PIXELS,psm.unpack_skip_pixels);
3763 glPixelStorei(GL_UNPACK_ROW_LENGTH, psm.unpack_row_length);
3764 glPixelStorei(GL_UNPACK_SWAP_BYTES, psm.unpack_swap_bytes);
3765 free(newImage);
3766 return GLU_OUT_OF_MEMORY;
3767 }
3768 }
3769 scale_internal(cmpts, newImage_width, newImage_height, newImage,
3770 newwidth, newheight, otherImage);
3771 /* Swap newImage and otherImage */
3772 imageTemp = otherImage;
3773 otherImage = newImage;
3774 newImage = imageTemp;
3775
3776 newImage_width = newwidth;
3777 newImage_height = newheight;
3778 glTexImage2D(target, level, internalFormat, newImage_width,
3779 newImage_height, 0, format, GL_UNSIGNED_SHORT,
3780 (void *) newImage);
3781 }
3782 if (newwidth > 1) newwidth /= 2;
3783 if (newheight > 1) newheight /= 2;
3784 }
3785 glPixelStorei(GL_UNPACK_ALIGNMENT, psm.unpack_alignment);
3786 glPixelStorei(GL_UNPACK_SKIP_ROWS, psm.unpack_skip_rows);
3787 glPixelStorei(GL_UNPACK_SKIP_PIXELS, psm.unpack_skip_pixels);
3788 glPixelStorei(GL_UNPACK_ROW_LENGTH, psm.unpack_row_length);
3789 glPixelStorei(GL_UNPACK_SWAP_BYTES, psm.unpack_swap_bytes);
3790
3791 free((GLbyte *) newImage);
3792 if (otherImage) {
3793 free((GLbyte *) otherImage);
3794 }
3795 return 0;
3796 }
3797
3798 /* To make swapping images less error prone */
3799 #define __GLU_INIT_SWAP_IMAGE void *tmpImage
3800 #define __GLU_SWAP_IMAGE(a,b) tmpImage = a; a = b; b = tmpImage;
3801
3802 static int gluBuild2DMipmapLevelsCore(GLenum target, GLint internalFormat,
3803 GLsizei width, GLsizei height,
3804 GLsizei widthPowerOf2,
3805 GLsizei heightPowerOf2,
3806 GLenum format, GLenum type,
3807 GLint userLevel,
3808 GLint baseLevel,GLint maxLevel,
3809 const void *data)
3810 {
3811 GLint newwidth, newheight;
3812 GLint level, levels;
3813 const void *usersImage; /* passed from user. Don't touch! */
3814 void *srcImage, *dstImage; /* scratch area to build mipmapped images */
3815 __GLU_INIT_SWAP_IMAGE;
3816 GLint memreq;
3817 GLint cmpts;
3818
3819 GLint myswap_bytes, groups_per_line, element_size, group_size;
3820 GLint rowsize, padding;
3821 PixelStorageModes psm;
3822
3823 assert(checkMipmapArgs(internalFormat,format,type) == 0);
3824 assert(width >= 1 && height >= 1);
3825
3826 if(type == GL_BITMAP) {
3827 return bitmapBuild2DMipmaps(target, internalFormat, width, height,
3828 format, type, data);
3829 }
3830
3831 srcImage = dstImage = NULL;
3832
3833 newwidth= widthPowerOf2;
3834 newheight= heightPowerOf2;
3835 levels = computeLog(newwidth);
3836 level = computeLog(newheight);
3837 if (level > levels) levels=level;
3838
3839 levels+= userLevel;
3840
3841 retrieveStoreModes(&psm);
3842 myswap_bytes = psm.unpack_swap_bytes;
3843 cmpts = elements_per_group(format,type);
3844 if (psm.unpack_row_length > 0) {
3845 groups_per_line = psm.unpack_row_length;
3846 } else {
3847 groups_per_line = width;
3848 }
3849
3850 element_size = bytes_per_element(type);
3851 group_size = element_size * cmpts;
3852 if (element_size == 1) myswap_bytes = 0;
3853
3854 rowsize = groups_per_line * group_size;
3855 padding = (rowsize % psm.unpack_alignment);
3856 if (padding) {
3857 rowsize += psm.unpack_alignment - padding;
3858 }
3859 usersImage = (const GLubyte *) data + psm.unpack_skip_rows * rowsize +
3860 psm.unpack_skip_pixels * group_size;
3861
3862 glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
3863 glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
3864 glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
3865
3866 level = userLevel;
3867
3868 /* already power-of-two square */
3869 if (width == newwidth && height == newheight) {
3870 /* Use usersImage for level userLevel */
3871 if (baseLevel <= level && level <= maxLevel) {
3872 glPixelStorei(GL_UNPACK_ROW_LENGTH, psm.unpack_row_length);
3873 glTexImage2D(target, level, internalFormat, width,
3874 height, 0, format, type,
3875 usersImage);
3876 }
3877 glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
3878 if(levels == 0) { /* we're done. clean up and return */
3879 glPixelStorei(GL_UNPACK_ALIGNMENT, psm.unpack_alignment);
3880 glPixelStorei(GL_UNPACK_SKIP_ROWS, psm.unpack_skip_rows);
3881 glPixelStorei(GL_UNPACK_SKIP_PIXELS, psm.unpack_skip_pixels);
3882 glPixelStorei(GL_UNPACK_ROW_LENGTH, psm.unpack_row_length);
3883 glPixelStorei(GL_UNPACK_SWAP_BYTES, psm.unpack_swap_bytes);
3884 return 0;
3885 }
3886 {
3887 int nextWidth= newwidth/2;
3888 int nextHeight= newheight/2;
3889
3890 /* clamp to 1 */
3891 if (nextWidth < 1) nextWidth= 1;
3892 if (nextHeight < 1) nextHeight= 1;
3893 memreq = image_size(nextWidth, nextHeight, format, type);
3894 }
3895
3896 switch(type) {
3897 case GL_UNSIGNED_BYTE:
3898 dstImage = (GLubyte *)malloc(memreq);
3899 break;
3900 case GL_BYTE:
3901 dstImage = (GLbyte *)malloc(memreq);
3902 break;
3903 case GL_UNSIGNED_SHORT:
3904 dstImage = (GLushort *)malloc(memreq);
3905 break;
3906 case GL_SHORT:
3907 dstImage = (GLshort *)malloc(memreq);
3908 break;
3909 case GL_UNSIGNED_INT:
3910 dstImage = (GLuint *)malloc(memreq);
3911 break;
3912 case GL_INT:
3913 dstImage = (GLint *)malloc(memreq);
3914 break;
3915 case GL_FLOAT:
3916 dstImage = (GLfloat *)malloc(memreq);
3917 break;
3918 case GL_UNSIGNED_BYTE_3_3_2:
3919 case GL_UNSIGNED_BYTE_2_3_3_REV:
3920 dstImage = (GLubyte *)malloc(memreq);
3921 break;
3922 case GL_UNSIGNED_SHORT_5_6_5:
3923 case GL_UNSIGNED_SHORT_5_6_5_REV:
3924 case GL_UNSIGNED_SHORT_4_4_4_4:
3925 case GL_UNSIGNED_SHORT_4_4_4_4_REV:
3926 case GL_UNSIGNED_SHORT_5_5_5_1:
3927 case GL_UNSIGNED_SHORT_1_5_5_5_REV:
3928 dstImage = (GLushort *)malloc(memreq);
3929 break;
3930 case GL_UNSIGNED_INT_8_8_8_8:
3931 case GL_UNSIGNED_INT_8_8_8_8_REV:
3932 case GL_UNSIGNED_INT_10_10_10_2:
3933 case GL_UNSIGNED_INT_2_10_10_10_REV:
3934 dstImage = (GLuint *)malloc(memreq);
3935 break;
3936 default:
3937 return GLU_INVALID_ENUM;
3938 }
3939 if (dstImage == NULL) {
3940 glPixelStorei(GL_UNPACK_ALIGNMENT, psm.unpack_alignment);
3941 glPixelStorei(GL_UNPACK_SKIP_ROWS, psm.unpack_skip_rows);
3942 glPixelStorei(GL_UNPACK_SKIP_PIXELS, psm.unpack_skip_pixels);
3943 glPixelStorei(GL_UNPACK_ROW_LENGTH, psm.unpack_row_length);
3944 glPixelStorei(GL_UNPACK_SWAP_BYTES, psm.unpack_swap_bytes);
3945 return GLU_OUT_OF_MEMORY;
3946 }
3947 else
3948 switch(type) {
3949 case GL_UNSIGNED_BYTE:
3950 halveImage_ubyte(cmpts, width, height,
3951 (const GLubyte *)usersImage, (GLubyte *)dstImage,
3952 element_size, rowsize, group_size);
3953 break;
3954 case GL_BYTE:
3955 halveImage_byte(cmpts, width, height,
3956 (const GLbyte *)usersImage, (GLbyte *)dstImage,
3957 element_size, rowsize, group_size);
3958 break;
3959 case GL_UNSIGNED_SHORT:
3960 halveImage_ushort(cmpts, width, height,
3961 (const GLushort *)usersImage, (GLushort *)dstImage,
3962 element_size, rowsize, group_size, myswap_bytes);
3963 break;
3964 case GL_SHORT:
3965 halveImage_short(cmpts, width, height,
3966 (const GLshort *)usersImage, (GLshort *)dstImage,
3967 element_size, rowsize, group_size, myswap_bytes);
3968 break;
3969 case GL_UNSIGNED_INT:
3970 halveImage_uint(cmpts, width, height,
3971 (const GLuint *)usersImage, (GLuint *)dstImage,
3972 element_size, rowsize, group_size, myswap_bytes);
3973 break;
3974 case GL_INT:
3975 halveImage_int(cmpts, width, height,
3976 (const GLint *)usersImage, (GLint *)dstImage,
3977 element_size, rowsize, group_size, myswap_bytes);
3978 break;
3979 case GL_FLOAT:
3980 halveImage_float(cmpts, width, height,
3981 (const GLfloat *)usersImage, (GLfloat *)dstImage,
3982 element_size, rowsize, group_size, myswap_bytes);
3983 break;
3984 case GL_UNSIGNED_BYTE_3_3_2:
3985 assert(format == GL_RGB);
3986 halveImagePackedPixel(3,extract332,shove332,
3987 width,height,usersImage,dstImage,
3988 element_size,rowsize,myswap_bytes);
3989 break;
3990 case GL_UNSIGNED_BYTE_2_3_3_REV:
3991 assert(format == GL_RGB);
3992 halveImagePackedPixel(3,extract233rev,shove233rev,
3993 width,height,usersImage,dstImage,
3994 element_size,rowsize,myswap_bytes);
3995 break;
3996 case GL_UNSIGNED_SHORT_5_6_5:
3997 halveImagePackedPixel(3,extract565,shove565,
3998 width,height,usersImage,dstImage,
3999 element_size,rowsize,myswap_bytes);
4000 break;
4001 case GL_UNSIGNED_SHORT_5_6_5_REV:
4002 halveImagePackedPixel(3,extract565rev,shove565rev,
4003 width,height,usersImage,dstImage,
4004 element_size,rowsize,myswap_bytes);
4005 break;
4006 case GL_UNSIGNED_SHORT_4_4_4_4:
4007 halveImagePackedPixel(4,extract4444,shove4444,
4008 width,height,usersImage,dstImage,
4009 element_size,rowsize,myswap_bytes);
4010 break;
4011 case GL_UNSIGNED_SHORT_4_4_4_4_REV:
4012 halveImagePackedPixel(4,extract4444rev,shove4444rev,
4013 width,height,usersImage,dstImage,
4014 element_size,rowsize,myswap_bytes);
4015 break;
4016 case GL_UNSIGNED_SHORT_5_5_5_1:
4017 halveImagePackedPixel(4,extract5551,shove5551,
4018 width,height,usersImage,dstImage,
4019 element_size,rowsize,myswap_bytes);
4020 break;
4021 case GL_UNSIGNED_SHORT_1_5_5_5_REV:
4022 halveImagePackedPixel(4,extract1555rev,shove1555rev,
4023 width,height,usersImage,dstImage,
4024 element_size,rowsize,myswap_bytes);
4025 break;
4026 case GL_UNSIGNED_INT_8_8_8_8:
4027 halveImagePackedPixel(4,extract8888,shove8888,
4028 width,height,usersImage,dstImage,
4029 element_size,rowsize,myswap_bytes);
4030 break;
4031 case GL_UNSIGNED_INT_8_8_8_8_REV:
4032 halveImagePackedPixel(4,extract8888rev,shove8888rev,
4033 width,height,usersImage,dstImage,
4034 element_size,rowsize,myswap_bytes);
4035 break;
4036 case GL_UNSIGNED_INT_10_10_10_2:
4037 halveImagePackedPixel(4,extract1010102,shove1010102,
4038 width,height,usersImage,dstImage,
4039 element_size,rowsize,myswap_bytes);
4040 break;
4041 case GL_UNSIGNED_INT_2_10_10_10_REV:
4042 halveImagePackedPixel(4,extract2101010rev,shove2101010rev,
4043 width,height,usersImage,dstImage,
4044 element_size,rowsize,myswap_bytes);
4045 break;
4046 default:
4047 assert(0);
4048 break;
4049 }
4050 newwidth = width/2;
4051 newheight = height/2;
4052 /* clamp to 1 */
4053 if (newwidth < 1) newwidth= 1;
4054 if (newheight < 1) newheight= 1;
4055
4056 myswap_bytes = 0;
4057 rowsize = newwidth * group_size;
4058 memreq = image_size(newwidth, newheight, format, type);
4059 /* Swap srcImage and dstImage */
4060 __GLU_SWAP_IMAGE(srcImage,dstImage);
4061 switch(type) {
4062 case GL_UNSIGNED_BYTE:
4063 dstImage = (GLubyte *)malloc(memreq);
4064 break;
4065 case GL_BYTE:
4066 dstImage = (GLbyte *)malloc(memreq);
4067 break;
4068 case GL_UNSIGNED_SHORT:
4069 dstImage = (GLushort *)malloc(memreq);
4070 break;
4071 case GL_SHORT:
4072 dstImage = (GLshort *)malloc(memreq);
4073 break;
4074 case GL_UNSIGNED_INT:
4075 dstImage = (GLuint *)malloc(memreq);
4076 break;
4077 case GL_INT:
4078 dstImage = (GLint *)malloc(memreq);
4079 break;
4080 case GL_FLOAT:
4081 dstImage = (GLfloat *)malloc(memreq);
4082 break;
4083 case GL_UNSIGNED_BYTE_3_3_2:
4084 case GL_UNSIGNED_BYTE_2_3_3_REV:
4085 dstImage = (GLubyte *)malloc(memreq);
4086 break;
4087 case GL_UNSIGNED_SHORT_5_6_5:
4088 case GL_UNSIGNED_SHORT_5_6_5_REV:
4089 case GL_UNSIGNED_SHORT_4_4_4_4:
4090 case GL_UNSIGNED_SHORT_4_4_4_4_REV:
4091 case GL_UNSIGNED_SHORT_5_5_5_1:
4092 case GL_UNSIGNED_SHORT_1_5_5_5_REV:
4093 dstImage = (GLushort *)malloc(memreq);
4094 break;
4095 case GL_UNSIGNED_INT_8_8_8_8:
4096 case GL_UNSIGNED_INT_8_8_8_8_REV:
4097 case GL_UNSIGNED_INT_10_10_10_2:
4098 case GL_UNSIGNED_INT_2_10_10_10_REV:
4099 dstImage = (GLuint *)malloc(memreq);
4100 break;
4101 default:
4102 return GLU_INVALID_ENUM;
4103 }
4104 if (dstImage == NULL) {
4105 glPixelStorei(GL_UNPACK_ALIGNMENT, psm.unpack_alignment);
4106 glPixelStorei(GL_UNPACK_SKIP_ROWS, psm.unpack_skip_rows);
4107 glPixelStorei(GL_UNPACK_SKIP_PIXELS, psm.unpack_skip_pixels);
4108 glPixelStorei(GL_UNPACK_ROW_LENGTH, psm.unpack_row_length);
4109 glPixelStorei(GL_UNPACK_SWAP_BYTES, psm.unpack_swap_bytes);
4110 return GLU_OUT_OF_MEMORY;
4111 }
4112 /* level userLevel+1 is in srcImage; level userLevel already saved */
4113 level = userLevel+1;
4114 } else { /* user's image is *not* nice power-of-2 sized square */
4115 memreq = image_size(newwidth, newheight, format, type);
4116 switch(type) {
4117 case GL_UNSIGNED_BYTE:
4118 dstImage = (GLubyte *)malloc(memreq);
4119 break;
4120 case GL_BYTE:
4121 dstImage = (GLbyte *)malloc(memreq);
4122 break;
4123 case GL_UNSIGNED_SHORT:
4124 dstImage = (GLushort *)malloc(memreq);
4125 break;
4126 case GL_SHORT:
4127 dstImage = (GLshort *)malloc(memreq);
4128 break;
4129 case GL_UNSIGNED_INT:
4130 dstImage = (GLuint *)malloc(memreq);
4131 break;
4132 case GL_INT:
4133 dstImage = (GLint *)malloc(memreq);
4134 break;
4135 case GL_FLOAT:
4136 dstImage = (GLfloat *)malloc(memreq);
4137 break;
4138 case GL_UNSIGNED_BYTE_3_3_2:
4139 case GL_UNSIGNED_BYTE_2_3_3_REV:
4140 dstImage = (GLubyte *)malloc(memreq);
4141 break;
4142 case GL_UNSIGNED_SHORT_5_6_5:
4143 case GL_UNSIGNED_SHORT_5_6_5_REV:
4144 case GL_UNSIGNED_SHORT_4_4_4_4:
4145 case GL_UNSIGNED_SHORT_4_4_4_4_REV:
4146 case GL_UNSIGNED_SHORT_5_5_5_1:
4147 case GL_UNSIGNED_SHORT_1_5_5_5_REV:
4148 dstImage = (GLushort *)malloc(memreq);
4149 break;
4150 case GL_UNSIGNED_INT_8_8_8_8:
4151 case GL_UNSIGNED_INT_8_8_8_8_REV:
4152 case GL_UNSIGNED_INT_10_10_10_2:
4153 case GL_UNSIGNED_INT_2_10_10_10_REV:
4154 dstImage = (GLuint *)malloc(memreq);
4155 break;
4156 default:
4157 return GLU_INVALID_ENUM;
4158 }
4159
4160 if (dstImage == NULL) {
4161 glPixelStorei(GL_UNPACK_ALIGNMENT, psm.unpack_alignment);
4162 glPixelStorei(GL_UNPACK_SKIP_ROWS, psm.unpack_skip_rows);
4163 glPixelStorei(GL_UNPACK_SKIP_PIXELS, psm.unpack_skip_pixels);
4164 glPixelStorei(GL_UNPACK_ROW_LENGTH, psm.unpack_row_length);
4165 glPixelStorei(GL_UNPACK_SWAP_BYTES, psm.unpack_swap_bytes);
4166 return GLU_OUT_OF_MEMORY;
4167 }
4168
4169 switch(type) {
4170 case GL_UNSIGNED_BYTE:
4171 scale_internal_ubyte(cmpts, width, height,
4172 (const GLubyte *)usersImage, newwidth, newheight,
4173 (GLubyte *)dstImage, element_size,
4174 rowsize, group_size);
4175 break;
4176 case GL_BYTE:
4177 scale_internal_byte(cmpts, width, height,
4178 (const GLbyte *)usersImage, newwidth, newheight,
4179 (GLbyte *)dstImage, element_size,
4180 rowsize, group_size);
4181 break;
4182 case GL_UNSIGNED_SHORT:
4183 scale_internal_ushort(cmpts, width, height,
4184 (const GLushort *)usersImage, newwidth, newheight,
4185 (GLushort *)dstImage, element_size,
4186 rowsize, group_size, myswap_bytes);
4187 break;
4188 case GL_SHORT:
4189 scale_internal_short(cmpts, width, height,
4190 (const GLshort *)usersImage, newwidth, newheight,
4191 (GLshort *)dstImage, element_size,
4192 rowsize, group_size, myswap_bytes);
4193 break;
4194 case GL_UNSIGNED_INT:
4195 scale_internal_uint(cmpts, width, height,
4196 (const GLuint *)usersImage, newwidth, newheight,
4197 (GLuint *)dstImage, element_size,
4198 rowsize, group_size, myswap_bytes);
4199 break;
4200 case GL_INT:
4201 scale_internal_int(cmpts, width, height,
4202 (const GLint *)usersImage, newwidth, newheight,
4203 (GLint *)dstImage, element_size,
4204 rowsize, group_size, myswap_bytes);
4205 break;
4206 case GL_FLOAT:
4207 scale_internal_float(cmpts, width, height,
4208 (const GLfloat *)usersImage, newwidth, newheight,
4209 (GLfloat *)dstImage, element_size,
4210 rowsize, group_size, myswap_bytes);
4211 break;
4212 case GL_UNSIGNED_BYTE_3_3_2:
4213 scaleInternalPackedPixel(3,extract332,shove332,
4214 width, height,usersImage,
4215 newwidth,newheight,(void *)dstImage,
4216 element_size,rowsize,myswap_bytes);
4217 break;
4218 case GL_UNSIGNED_BYTE_2_3_3_REV:
4219 scaleInternalPackedPixel(3,extract233rev,shove233rev,
4220 width, height,usersImage,
4221 newwidth,newheight,(void *)dstImage,
4222 element_size,rowsize,myswap_bytes);
4223 break;
4224 case GL_UNSIGNED_SHORT_5_6_5:
4225 scaleInternalPackedPixel(3,extract565,shove565,
4226 width, height,usersImage,
4227 newwidth,newheight,(void *)dstImage,
4228 element_size,rowsize,myswap_bytes);
4229 break;
4230 case GL_UNSIGNED_SHORT_5_6_5_REV:
4231 scaleInternalPackedPixel(3,extract565rev,shove565rev,
4232 width, height,usersImage,
4233 newwidth,newheight,(void *)dstImage,
4234 element_size,rowsize,myswap_bytes);
4235 break;
4236 case GL_UNSIGNED_SHORT_4_4_4_4:
4237 scaleInternalPackedPixel(4,extract4444,shove4444,
4238 width, height,usersImage,
4239 newwidth,newheight,(void *)dstImage,
4240 element_size,rowsize,myswap_bytes);
4241 break;
4242 case GL_UNSIGNED_SHORT_4_4_4_4_REV:
4243 scaleInternalPackedPixel(4,extract4444rev,shove4444rev,
4244 width, height,usersImage,
4245 newwidth,newheight,(void *)dstImage,
4246 element_size,rowsize,myswap_bytes);
4247 break;
4248 case GL_UNSIGNED_SHORT_5_5_5_1:
4249 scaleInternalPackedPixel(4,extract5551,shove5551,
4250 width, height,usersImage,
4251 newwidth,newheight,(void *)dstImage,
4252 element_size,rowsize,myswap_bytes);
4253 break;
4254 case GL_UNSIGNED_SHORT_1_5_5_5_REV:
4255 scaleInternalPackedPixel(4,extract1555rev,shove1555rev,
4256 width, height,usersImage,
4257 newwidth,newheight,(void *)dstImage,
4258 element_size,rowsize,myswap_bytes);
4259 break;
4260 case GL_UNSIGNED_INT_8_8_8_8:
4261 scaleInternalPackedPixel(4,extract8888,shove8888,
4262 width, height,usersImage,
4263 newwidth,newheight,(void *)dstImage,
4264 element_size,rowsize,myswap_bytes);
4265 break;
4266 case GL_UNSIGNED_INT_8_8_8_8_REV:
4267 scaleInternalPackedPixel(4,extract8888rev,shove8888rev,
4268 width, height,usersImage,
4269 newwidth,newheight,(void *)dstImage,
4270 element_size,rowsize,myswap_bytes);
4271 break;
4272 case GL_UNSIGNED_INT_10_10_10_2:
4273 scaleInternalPackedPixel(4,extract1010102,shove1010102,
4274 width, height,usersImage,
4275 newwidth,newheight,(void *)dstImage,
4276 element_size,rowsize,myswap_bytes);
4277 break;
4278 case GL_UNSIGNED_INT_2_10_10_10_REV:
4279 scaleInternalPackedPixel(4,extract2101010rev,shove2101010rev,
4280 width, height,usersImage,
4281 newwidth,newheight,(void *)dstImage,
4282 element_size,rowsize,myswap_bytes);
4283 break;
4284 default:
4285 assert(0);
4286 break;
4287 }
4288 myswap_bytes = 0;
4289 rowsize = newwidth * group_size;
4290 /* Swap dstImage and srcImage */
4291 __GLU_SWAP_IMAGE(srcImage,dstImage);
4292
4293 if(levels != 0) { /* use as little memory as possible */
4294 {
4295 int nextWidth= newwidth/2;
4296 int nextHeight= newheight/2;
4297 if (nextWidth < 1) nextWidth= 1;
4298 if (nextHeight < 1) nextHeight= 1;
4299
4300 memreq = image_size(nextWidth, nextHeight, format, type);
4301 }
4302
4303 switch(type) {
4304 case GL_UNSIGNED_BYTE:
4305 dstImage = (GLubyte *)malloc(memreq);
4306 break;
4307 case GL_BYTE:
4308 dstImage = (GLbyte *)malloc(memreq);
4309 break;
4310 case GL_UNSIGNED_SHORT:
4311 dstImage = (GLushort *)malloc(memreq);
4312 break;
4313 case GL_SHORT:
4314 dstImage = (GLshort *)malloc(memreq);
4315 break;
4316 case GL_UNSIGNED_INT:
4317 dstImage = (GLuint *)malloc(memreq);
4318 break;
4319 case GL_INT:
4320 dstImage = (GLint *)malloc(memreq);
4321 break;
4322 case GL_FLOAT:
4323 dstImage = (GLfloat *)malloc(memreq);
4324 break;
4325 case GL_UNSIGNED_BYTE_3_3_2:
4326 case GL_UNSIGNED_BYTE_2_3_3_REV:
4327 dstImage = (GLubyte *)malloc(memreq);
4328 break;
4329 case GL_UNSIGNED_SHORT_5_6_5:
4330 case GL_UNSIGNED_SHORT_5_6_5_REV:
4331 case GL_UNSIGNED_SHORT_4_4_4_4:
4332 case GL_UNSIGNED_SHORT_4_4_4_4_REV:
4333 case GL_UNSIGNED_SHORT_5_5_5_1:
4334 case GL_UNSIGNED_SHORT_1_5_5_5_REV:
4335 dstImage = (GLushort *)malloc(memreq);
4336 break;
4337 case GL_UNSIGNED_INT_8_8_8_8:
4338 case GL_UNSIGNED_INT_8_8_8_8_REV:
4339 case GL_UNSIGNED_INT_10_10_10_2:
4340 case GL_UNSIGNED_INT_2_10_10_10_REV:
4341 dstImage = (GLuint *)malloc(memreq);
4342 break;
4343 default:
4344 return GLU_INVALID_ENUM;
4345 }
4346 if (dstImage == NULL) {
4347 glPixelStorei(GL_UNPACK_ALIGNMENT, psm.unpack_alignment);
4348 glPixelStorei(GL_UNPACK_SKIP_ROWS, psm.unpack_skip_rows);
4349 glPixelStorei(GL_UNPACK_SKIP_PIXELS, psm.unpack_skip_pixels);
4350 glPixelStorei(GL_UNPACK_ROW_LENGTH, psm.unpack_row_length);
4351 glPixelStorei(GL_UNPACK_SWAP_BYTES, psm.unpack_swap_bytes);
4352 return GLU_OUT_OF_MEMORY;
4353 }
4354 }
4355 /* level userLevel is in srcImage; nothing saved yet */
4356 level = userLevel;
4357 }
4358
4359 glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE);
4360 if (baseLevel <= level && level <= maxLevel) {
4361 glTexImage2D(target, level, internalFormat, newwidth, newheight, 0,
4362 format, type, (void *)srcImage);
4363 }
4364
4365 level++; /* update current level for the loop */
4366 for (; level <= levels; level++) {
4367 switch(type) {
4368 case GL_UNSIGNED_BYTE:
4369 halveImage_ubyte(cmpts, newwidth, newheight,
4370 (GLubyte *)srcImage, (GLubyte *)dstImage, element_size,
4371 rowsize, group_size);
4372 break;
4373 case GL_BYTE:
4374 halveImage_byte(cmpts, newwidth, newheight,
4375 (GLbyte *)srcImage, (GLbyte *)dstImage, element_size,
4376 rowsize, group_size);
4377 break;
4378 case GL_UNSIGNED_SHORT:
4379 halveImage_ushort(cmpts, newwidth, newheight,
4380 (GLushort *)srcImage, (GLushort *)dstImage, element_size,
4381 rowsize, group_size, myswap_bytes);
4382 break;
4383 case GL_SHORT:
4384 halveImage_short(cmpts, newwidth, newheight,
4385 (GLshort *)srcImage, (GLshort *)dstImage, element_size,
4386 rowsize, group_size, myswap_bytes);
4387 break;
4388 case GL_UNSIGNED_INT:
4389 halveImage_uint(cmpts, newwidth, newheight,
4390 (GLuint *)srcImage, (GLuint *)dstImage, element_size,
4391 rowsize, group_size, myswap_bytes);
4392 break;
4393 case GL_INT:
4394 halveImage_int(cmpts, newwidth, newheight,
4395 (GLint *)srcImage, (GLint *)dstImage, element_size,
4396 rowsize, group_size, myswap_bytes);
4397 break;
4398 case GL_FLOAT:
4399 halveImage_float(cmpts, newwidth, newheight,
4400 (GLfloat *)srcImage, (GLfloat *)dstImage, element_size,
4401 rowsize, group_size, myswap_bytes);
4402 break;
4403 case GL_UNSIGNED_BYTE_3_3_2:
4404 halveImagePackedPixel(3,extract332,shove332,
4405 newwidth,newheight,
4406 srcImage,dstImage,element_size,rowsize,
4407 myswap_bytes);
4408 break;
4409 case GL_UNSIGNED_BYTE_2_3_3_REV:
4410 halveImagePackedPixel(3,extract233rev,shove233rev,
4411 newwidth,newheight,
4412 srcImage,dstImage,element_size,rowsize,
4413 myswap_bytes);
4414 break;
4415 case GL_UNSIGNED_SHORT_5_6_5:
4416 halveImagePackedPixel(3,extract565,shove565,
4417 newwidth,newheight,
4418 srcImage,dstImage,element_size,rowsize,
4419 myswap_bytes);
4420 break;
4421 case GL_UNSIGNED_SHORT_5_6_5_REV:
4422 halveImagePackedPixel(3,extract565rev,shove565rev,
4423 newwidth,newheight,
4424 srcImage,dstImage,element_size,rowsize,
4425 myswap_bytes);
4426 break;
4427 case GL_UNSIGNED_SHORT_4_4_4_4:
4428 halveImagePackedPixel(4,extract4444,shove4444,
4429 newwidth,newheight,
4430 srcImage,dstImage,element_size,rowsize,
4431 myswap_bytes);
4432 break;
4433 case GL_UNSIGNED_SHORT_4_4_4_4_REV:
4434 halveImagePackedPixel(4,extract4444rev,shove4444rev,
4435 newwidth,newheight,
4436 srcImage,dstImage,element_size,rowsize,
4437 myswap_bytes);
4438 break;
4439 case GL_UNSIGNED_SHORT_5_5_5_1:
4440 halveImagePackedPixel(4,extract5551,shove5551,
4441 newwidth,newheight,
4442 srcImage,dstImage,element_size,rowsize,
4443 myswap_bytes);
4444 break;
4445 case GL_UNSIGNED_SHORT_1_5_5_5_REV:
4446 halveImagePackedPixel(4,extract1555rev,shove1555rev,
4447 newwidth,newheight,
4448 srcImage,dstImage,element_size,rowsize,
4449 myswap_bytes);
4450 break;
4451 case GL_UNSIGNED_INT_8_8_8_8:
4452 halveImagePackedPixel(4,extract8888,shove8888,
4453 newwidth,newheight,
4454 srcImage,dstImage,element_size,rowsize,
4455 myswap_bytes);
4456 break;
4457 case GL_UNSIGNED_INT_8_8_8_8_REV:
4458 halveImagePackedPixel(4,extract8888rev,shove8888rev,
4459 newwidth,newheight,
4460 srcImage,dstImage,element_size,rowsize,
4461 myswap_bytes);
4462 break;
4463 case GL_UNSIGNED_INT_10_10_10_2:
4464 halveImagePackedPixel(4,extract1010102,shove1010102,
4465 newwidth,newheight,
4466 srcImage,dstImage,element_size,rowsize,
4467 myswap_bytes);
4468 break;
4469 case GL_UNSIGNED_INT_2_10_10_10_REV:
4470 halveImagePackedPixel(4,extract2101010rev,shove2101010rev,
4471 newwidth,newheight,
4472 srcImage,dstImage,element_size,rowsize,
4473 myswap_bytes);
4474 break;
4475 default:
4476 assert(0);
4477 break;
4478 }
4479
4480 __GLU_SWAP_IMAGE(srcImage,dstImage);
4481
4482 if (newwidth > 1) { newwidth /= 2; rowsize /= 2;}
4483 if (newheight > 1) newheight /= 2;
4484 {
4485 /* compute amount to pad per row, if any */
4486 int rowPad= rowsize % psm.unpack_alignment;
4487
4488 /* should row be padded? */
4489 if (rowPad == 0) { /* nope, row should not be padded */
4490 /* call tex image with srcImage untouched since it's not padded */
4491 if (baseLevel <= level && level <= maxLevel) {
4492 glTexImage2D(target, level, internalFormat, newwidth, newheight, 0,
4493 format, type, (void *) srcImage);
4494 }
4495 }
4496 else { /* yes, row should be padded */
4497 /* compute length of new row in bytes, including padding */
4498 int newRowLength= rowsize + psm.unpack_alignment - rowPad;
4499 int ii; unsigned char *dstTrav, *srcTrav; /* indices for copying */
4500
4501 /* allocate new image for mipmap of size newRowLength x newheight */
4502 void *newMipmapImage= malloc((size_t) (newRowLength*newheight));
4503 if (newMipmapImage == NULL) {
4504 /* out of memory so return */
4505 glPixelStorei(GL_UNPACK_ALIGNMENT, psm.unpack_alignment);
4506 glPixelStorei(GL_UNPACK_SKIP_ROWS, psm.unpack_skip_rows);
4507 glPixelStorei(GL_UNPACK_SKIP_PIXELS, psm.unpack_skip_pixels);
4508 glPixelStorei(GL_UNPACK_ROW_LENGTH, psm.unpack_row_length);
4509 glPixelStorei(GL_UNPACK_SWAP_BYTES, psm.unpack_swap_bytes);
4510 return GLU_OUT_OF_MEMORY;
4511 }
4512
4513 /* copy image from srcImage into newMipmapImage by rows */
4514 for (ii= 0,
4515 dstTrav= (unsigned char *) newMipmapImage,
4516 srcTrav= (unsigned char *) srcImage;
4517 ii< newheight;
4518 ii++,
4519 dstTrav+= newRowLength, /* make sure the correct distance... */
4520 srcTrav+= rowsize) { /* ...is skipped */
4521 memcpy(dstTrav,srcTrav,rowsize);
4522 /* note that the pad bytes are not visited and will contain
4523 * garbage, which is ok.
4524 */
4525 }
4526
4527 /* ...and use this new image for mipmapping instead */
4528 if (baseLevel <= level && level <= maxLevel) {
4529 glTexImage2D(target, level, internalFormat, newwidth, newheight, 0,
4530 format, type, newMipmapImage);
4531 }
4532 free(newMipmapImage); /* don't forget to free it! */
4533 } /* else */
4534 }
4535 } /* for level */
4536 glPixelStorei(GL_UNPACK_ALIGNMENT, psm.unpack_alignment);
4537 glPixelStorei(GL_UNPACK_SKIP_ROWS, psm.unpack_skip_rows);
4538 glPixelStorei(GL_UNPACK_SKIP_PIXELS, psm.unpack_skip_pixels);
4539 glPixelStorei(GL_UNPACK_ROW_LENGTH, psm.unpack_row_length);
4540 glPixelStorei(GL_UNPACK_SWAP_BYTES, psm.unpack_swap_bytes);
4541
4542 free(srcImage); /*if you get to here, a srcImage has always been malloc'ed*/
4543 if (dstImage) { /* if it's non-rectangular and only 1 level */
4544 free(dstImage);
4545 }
4546 return 0;
4547 } /* gluBuild2DMipmapLevelsCore() */
4548
4549 GLint GLAPIENTRY
4550 gluBuild2DMipmapLevels(GLenum target, GLint internalFormat,
4551 GLsizei width, GLsizei height,
4552 GLenum format, GLenum type,
4553 GLint userLevel, GLint baseLevel, GLint maxLevel,
4554 const void *data)
4555 {
4556 int level, levels;
4557
4558 int rc= checkMipmapArgs(internalFormat,format,type);
4559 if (rc != 0) return rc;
4560
4561 if (width < 1 || height < 1) {
4562 return GLU_INVALID_VALUE;
4563 }
4564
4565 levels = computeLog(width);
4566 level = computeLog(height);
4567 if (level > levels) levels=level;
4568
4569 levels+= userLevel;
4570 if (!isLegalLevels(userLevel,baseLevel,maxLevel,levels))
4571 return GLU_INVALID_VALUE;
4572
4573 return gluBuild2DMipmapLevelsCore(target, internalFormat,
4574 width, height,
4575 width, height,
4576 format, type,
4577 userLevel, baseLevel, maxLevel,
4578 data);
4579 } /* gluBuild2DMipmapLevels() */
4580
4581 GLint GLAPIENTRY
4582 gluBuild2DMipmaps(GLenum target, GLint internalFormat,
4583 GLsizei width, GLsizei height,
4584 GLenum format, GLenum type,
4585 const void *data)
4586 {
4587 GLint widthPowerOf2, heightPowerOf2;
4588 int level, levels;
4589
4590 int rc= checkMipmapArgs(internalFormat,format,type);
4591 if (rc != 0) return rc;
4592
4593 if (width < 1 || height < 1) {
4594 return GLU_INVALID_VALUE;
4595 }
4596
4597 closestFit(target,width,height,internalFormat,format,type,
4598 &widthPowerOf2,&heightPowerOf2);
4599
4600 levels = computeLog(widthPowerOf2);
4601 level = computeLog(heightPowerOf2);
4602 if (level > levels) levels=level;
4603
4604 return gluBuild2DMipmapLevelsCore(target,internalFormat,
4605 width, height,
4606 widthPowerOf2,heightPowerOf2,
4607 format,type,
4608 0,0,levels,data);
4609 } /* gluBuild2DMipmaps() */
4610
4611 #if 0
4612 /*
4613 ** This routine is for the limited case in which
4614 ** type == GL_UNSIGNED_BYTE && format != index &&
4615 ** unpack_alignment = 1 && unpack_swap_bytes == false
4616 **
4617 ** so all of the work data can be kept as ubytes instead of shorts.
4618 */
4619 static int fastBuild2DMipmaps(const PixelStorageModes *psm,
4620 GLenum target, GLint components, GLint width,
4621 GLint height, GLenum format,
4622 GLenum type, void *data)
4623 {
4624 GLint newwidth, newheight;
4625 GLint level, levels;
4626 GLubyte *newImage;
4627 GLint newImage_width;
4628 GLint newImage_height;
4629 GLubyte *otherImage;
4630 GLubyte *imageTemp;
4631 GLint memreq;
4632 GLint cmpts;
4633
4634
4635 #if 0
4636 glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxsize);
4637 newwidth = nearestPower(width);
4638 if (newwidth > maxsize) newwidth = maxsize;
4639 newheight = nearestPower(height);
4640 if (newheight > maxsize) newheight = maxsize;
4641 #else
4642 closestFit(target,width,height,components,format,type,
4643 &newwidth,&newheight);
4644 #endif
4645 levels = computeLog(newwidth);
4646 level = computeLog(newheight);
4647 if (level > levels) levels=level;
4648
4649 cmpts = elements_per_group(format,type);
4650
4651 otherImage = NULL;
4652 /**
4653 ** No need to copy the user data if its in the packed correctly.
4654 ** Make sure that later routines don't change that data.
4655 */
4656 if (psm->unpack_skip_rows == 0 && psm->unpack_skip_pixels == 0) {
4657 newImage = (GLubyte *)data;
4658 newImage_width = width;
4659 newImage_height = height;
4660 } else {
4661 GLint rowsize;
4662 GLint groups_per_line;
4663 GLint elements_per_line;
4664 const GLubyte *start;
4665 const GLubyte *iter;
4666 GLubyte *iter2;
4667 GLint i, j;
4668
4669 newImage = (GLubyte *)
4670 malloc(image_size(width, height, format, GL_UNSIGNED_BYTE));
4671 newImage_width = width;
4672 newImage_height = height;
4673 if (newImage == NULL) {
4674 return GLU_OUT_OF_MEMORY;
4675 }
4676
4677 /*
4678 ** Abbreviated version of fill_image for this restricted case.
4679 */
4680 if (psm->unpack_row_length > 0) {
4681 groups_per_line = psm->unpack_row_length;
4682 } else {
4683 groups_per_line = width;
4684 }
4685 rowsize = groups_per_line * cmpts;
4686 elements_per_line = width * cmpts;
4687 start = (const GLubyte *) data + psm->unpack_skip_rows * rowsize +
4688 psm->unpack_skip_pixels * cmpts;
4689 iter2 = newImage;
4690
4691 for (i = 0; i < height; i++) {
4692 iter = start;
4693 for (j = 0; j < elements_per_line; j++) {
4694 *iter2 = *iter;
4695 iter++;
4696 iter2++;
4697 }
4698 start += rowsize;
4699 }
4700 }
4701
4702
4703 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
4704 glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
4705 glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
4706 glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
4707 glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE);
4708
4709 for (level = 0; level <= levels; level++) {
4710 if (newImage_width == newwidth && newImage_height == newheight) {
4711 /* Use newImage for this level */
4712 glTexImage2D(target, level, components, newImage_width,
4713 newImage_height, 0, format, GL_UNSIGNED_BYTE,
4714 (void *) newImage);
4715 } else {
4716 if (otherImage == NULL) {
4717 memreq =
4718 image_size(newwidth, newheight, format, GL_UNSIGNED_BYTE);
4719 otherImage = (GLubyte *) malloc(memreq);
4720 if (otherImage == NULL) {
4721 glPixelStorei(GL_UNPACK_ALIGNMENT, psm->unpack_alignment);
4722 glPixelStorei(GL_UNPACK_SKIP_ROWS, psm->unpack_skip_rows);
4723 glPixelStorei(GL_UNPACK_SKIP_PIXELS, psm->unpack_skip_pixels);
4724 glPixelStorei(GL_UNPACK_ROW_LENGTH,psm->unpack_row_length);
4725 glPixelStorei(GL_UNPACK_SWAP_BYTES,psm->unpack_swap_bytes);
4726 return GLU_OUT_OF_MEMORY;
4727 }
4728 }
4729 /*
4730 scale_internal_ubyte(cmpts, newImage_width, newImage_height,
4731 newImage, newwidth, newheight, otherImage);
4732 */
4733 /* Swap newImage and otherImage */
4734 imageTemp = otherImage;
4735 otherImage = newImage;
4736 newImage = imageTemp;
4737
4738 newImage_width = newwidth;
4739 newImage_height = newheight;
4740 glTexImage2D(target, level, components, newImage_width,
4741 newImage_height, 0, format, GL_UNSIGNED_BYTE,
4742 (void *) newImage);
4743 }
4744 if (newwidth > 1) newwidth /= 2;
4745 if (newheight > 1) newheight /= 2;
4746 }
4747 glPixelStorei(GL_UNPACK_ALIGNMENT, psm->unpack_alignment);
4748 glPixelStorei(GL_UNPACK_SKIP_ROWS, psm->unpack_skip_rows);
4749 glPixelStorei(GL_UNPACK_SKIP_PIXELS, psm->unpack_skip_pixels);
4750 glPixelStorei(GL_UNPACK_ROW_LENGTH, psm->unpack_row_length);
4751 glPixelStorei(GL_UNPACK_SWAP_BYTES, psm->unpack_swap_bytes);
4752
4753 if (newImage != (const GLubyte *)data) {
4754 free((GLbyte *) newImage);
4755 }
4756 if (otherImage && otherImage != (const GLubyte *)data) {
4757 free((GLbyte *) otherImage);
4758 }
4759 return 0;
4760 }
4761 #endif
4762
4763 /*
4764 * Utility Routines
4765 */
4766 static GLint elements_per_group(GLenum format, GLenum type)
4767 {
4768 /*
4769 * Return the number of elements per group of a specified format
4770 */
4771
4772 /* If the type is packedpixels then answer is 1 (ignore format) */
4773 if (type == GL_UNSIGNED_BYTE_3_3_2 ||
4774 type == GL_UNSIGNED_BYTE_2_3_3_REV ||
4775 type == GL_UNSIGNED_SHORT_5_6_5 ||
4776 type == GL_UNSIGNED_SHORT_5_6_5_REV ||
4777 type == GL_UNSIGNED_SHORT_4_4_4_4 ||
4778 type == GL_UNSIGNED_SHORT_4_4_4_4_REV ||
4779 type == GL_UNSIGNED_SHORT_5_5_5_1 ||
4780 type == GL_UNSIGNED_SHORT_1_5_5_5_REV ||
4781 type == GL_UNSIGNED_INT_8_8_8_8 ||
4782 type == GL_UNSIGNED_INT_8_8_8_8_REV ||
4783 type == GL_UNSIGNED_INT_10_10_10_2 ||
4784 type == GL_UNSIGNED_INT_2_10_10_10_REV) {
4785 return 1;
4786 }
4787
4788 /* Types are not packed pixels, so get elements per group */
4789 switch(format) {
4790 case GL_RGB:
4791 case GL_BGR:
4792 return 3;
4793 case GL_LUMINANCE_ALPHA:
4794 return 2;
4795 case GL_RGBA:
4796 case GL_BGRA:
4797 return 4;
4798 default:
4799 return 1;
4800 }
4801 }
4802
4803 static GLfloat bytes_per_element(GLenum type)
4804 {
4805 /*
4806 * Return the number of bytes per element, based on the element type
4807 */
4808 switch(type) {
4809 case GL_BITMAP:
4810 return 1.0 / 8.0;
4811 case GL_UNSIGNED_SHORT:
4812 return(sizeof(GLushort));
4813 case GL_SHORT:
4814 return(sizeof(GLshort));
4815 case GL_UNSIGNED_BYTE:
4816 return(sizeof(GLubyte));
4817 case GL_BYTE:
4818 return(sizeof(GLbyte));
4819 case GL_INT:
4820 return(sizeof(GLint));
4821 case GL_UNSIGNED_INT:
4822 return(sizeof(GLuint));
4823 case GL_FLOAT:
4824 return(sizeof(GLfloat));
4825 case GL_UNSIGNED_BYTE_3_3_2:
4826 case GL_UNSIGNED_BYTE_2_3_3_REV:
4827 return(sizeof(GLubyte));
4828 case GL_UNSIGNED_SHORT_5_6_5:
4829 case GL_UNSIGNED_SHORT_5_6_5_REV:
4830 case GL_UNSIGNED_SHORT_4_4_4_4:
4831 case GL_UNSIGNED_SHORT_4_4_4_4_REV:
4832 case GL_UNSIGNED_SHORT_5_5_5_1:
4833 case GL_UNSIGNED_SHORT_1_5_5_5_REV:
4834 return(sizeof(GLushort));
4835 case GL_UNSIGNED_INT_8_8_8_8:
4836 case GL_UNSIGNED_INT_8_8_8_8_REV:
4837 case GL_UNSIGNED_INT_10_10_10_2:
4838 case GL_UNSIGNED_INT_2_10_10_10_REV:
4839 return(sizeof(GLuint));
4840 default:
4841 return 4;
4842 }
4843 }
4844
4845 static GLint is_index(GLenum format)
4846 {
4847 return format == GL_COLOR_INDEX || format == GL_STENCIL_INDEX;
4848 }
4849
4850 /*
4851 ** Compute memory required for internal packed array of data of given type
4852 ** and format.
4853 */
4854 static GLint image_size(GLint width, GLint height, GLenum format, GLenum type)
4855 {
4856 int bytes_per_row;
4857 int components;
4858
4859 assert(width > 0);
4860 assert(height > 0);
4861 components = elements_per_group(format,type);
4862 if (type == GL_BITMAP) {
4863 bytes_per_row = (width + 7) / 8;
4864 } else {
4865 bytes_per_row = bytes_per_element(type) * width;
4866 }
4867 return bytes_per_row * height * components;
4868 }
4869
4870 /*
4871 ** Extract array from user's data applying all pixel store modes.
4872 ** The internal format used is an array of unsigned shorts.
4873 */
4874 static void fill_image(const PixelStorageModes *psm,
4875 GLint width, GLint height, GLenum format,
4876 GLenum type, GLboolean index_format,
4877 const void *userdata, GLushort *newimage)
4878 {
4879 GLint components;
4880 GLint element_size;
4881 GLint rowsize;
4882 GLint padding;
4883 GLint groups_per_line;
4884 GLint group_size;
4885 GLint elements_per_line;
4886 const GLubyte *start;
4887 const GLubyte *iter;
4888 GLushort *iter2;
4889 GLint i, j, k;
4890 GLint myswap_bytes;
4891
4892 myswap_bytes = psm->unpack_swap_bytes;
4893 components = elements_per_group(format,type);
4894 if (psm->unpack_row_length > 0) {
4895 groups_per_line = psm->unpack_row_length;
4896 } else {
4897 groups_per_line = width;
4898 }
4899
4900 /* All formats except GL_BITMAP fall out trivially */
4901 if (type == GL_BITMAP) {
4902 GLint bit_offset;
4903 GLint current_bit;
4904
4905 rowsize = (groups_per_line * components + 7) / 8;
4906 padding = (rowsize % psm->unpack_alignment);
4907 if (padding) {
4908 rowsize += psm->unpack_alignment - padding;
4909 }
4910 start = (const GLubyte *) userdata + psm->unpack_skip_rows * rowsize +
4911 (psm->unpack_skip_pixels * components / 8);
4912 elements_per_line = width * components;
4913 iter2 = newimage;
4914 for (i = 0; i < height; i++) {
4915 iter = start;
4916 bit_offset = (psm->unpack_skip_pixels * components) % 8;
4917 for (j = 0; j < elements_per_line; j++) {
4918 /* Retrieve bit */
4919 if (psm->unpack_lsb_first) {
4920 current_bit = iter[0] & (1 << bit_offset);
4921 } else {
4922 current_bit = iter[0] & (1 << (7 - bit_offset));
4923 }
4924 if (current_bit) {
4925 if (index_format) {
4926 *iter2 = 1;
4927 } else {
4928 *iter2 = 65535;
4929 }
4930 } else {
4931 *iter2 = 0;
4932 }
4933 bit_offset++;
4934 if (bit_offset == 8) {
4935 bit_offset = 0;
4936 iter++;
4937 }
4938 iter2++;
4939 }
4940 start += rowsize;
4941 }
4942 } else {
4943 element_size = bytes_per_element(type);
4944 group_size = element_size * components;
4945 if (element_size == 1) myswap_bytes = 0;
4946
4947 rowsize = groups_per_line * group_size;
4948 padding = (rowsize % psm->unpack_alignment);
4949 if (padding) {
4950 rowsize += psm->unpack_alignment - padding;
4951 }
4952 start = (const GLubyte *) userdata + psm->unpack_skip_rows * rowsize +
4953 psm->unpack_skip_pixels * group_size;
4954 elements_per_line = width * components;
4955
4956 iter2 = newimage;
4957 for (i = 0; i < height; i++) {
4958 iter = start;
4959 for (j = 0; j < elements_per_line; j++) {
4960 Type_Widget widget;
4961 float extractComponents[4];
4962
4963 switch(type) {
4964 case GL_UNSIGNED_BYTE_3_3_2:
4965 extract332(0,iter,extractComponents);
4966 for (k = 0; k < 3; k++) {
4967 *iter2++ = (GLushort)(extractComponents[k]*65535);
4968 }
4969 break;
4970 case GL_UNSIGNED_BYTE_2_3_3_REV:
4971 extract233rev(0,iter,extractComponents);
4972 for (k = 0; k < 3; k++) {
4973 *iter2++ = (GLushort)(extractComponents[k]*65535);
4974 }
4975 break;
4976 case GL_UNSIGNED_BYTE:
4977 if (index_format) {
4978 *iter2++ = *iter;
4979 } else {
4980 *iter2++ = (*iter) * 257;
4981 }
4982 break;
4983 case GL_BYTE:
4984 if (index_format) {
4985 *iter2++ = *((const GLbyte *) iter);
4986 } else {
4987 /* rough approx */
4988 *iter2++ = (*((const GLbyte *) iter)) * 516;
4989 }
4990 break;
4991 case GL_UNSIGNED_SHORT_5_6_5:
4992 extract565(myswap_bytes,iter,extractComponents);
4993 for (k = 0; k < 3; k++) {
4994 *iter2++ = (GLushort)(extractComponents[k]*65535);
4995 }
4996 break;
4997 case GL_UNSIGNED_SHORT_5_6_5_REV:
4998 extract565rev(myswap_bytes,iter,extractComponents);
4999 for (k = 0; k < 3; k++) {
5000 *iter2++ = (GLushort)(extractComponents[k]*65535);
5001 }
5002 break;
5003 case GL_UNSIGNED_SHORT_4_4_4_4:
5004 extract4444(myswap_bytes,iter,extractComponents);
5005 for (k = 0; k < 4; k++) {
5006 *iter2++ = (GLushort)(extractComponents[k]*65535);
5007 }
5008 break;
5009 case GL_UNSIGNED_SHORT_4_4_4_4_REV:
5010 extract4444rev(myswap_bytes,iter,extractComponents);
5011 for (k = 0; k < 4; k++) {
5012 *iter2++ = (GLushort)(extractComponents[k]*65535);
5013 }
5014 break;
5015 case GL_UNSIGNED_SHORT_5_5_5_1:
5016 extract5551(myswap_bytes,iter,extractComponents);
5017 for (k = 0; k < 4; k++) {
5018 *iter2++ = (GLushort)(extractComponents[k]*65535);
5019 }
5020 break;
5021 case GL_UNSIGNED_SHORT_1_5_5_5_REV:
5022 extract1555rev(myswap_bytes,iter,extractComponents);
5023 for (k = 0; k < 4; k++) {
5024 *iter2++ = (GLushort)(extractComponents[k]*65535);
5025 }
5026 break;
5027 case GL_UNSIGNED_SHORT:
5028 case GL_SHORT:
5029 if (myswap_bytes) {
5030 widget.ub[0] = iter[1];
5031 widget.ub[1] = iter[0];
5032 } else {
5033 widget.ub[0] = iter[0];
5034 widget.ub[1] = iter[1];
5035 }
5036 if (type == GL_SHORT) {
5037 if (index_format) {
5038 *iter2++ = widget.s[0];
5039 } else {
5040 /* rough approx */
5041 *iter2++ = widget.s[0]*2;
5042 }
5043 } else {
5044 *iter2++ = widget.us[0];
5045 }
5046 break;
5047 case GL_UNSIGNED_INT_8_8_8_8:
5048 extract8888(myswap_bytes,iter,extractComponents);
5049 for (k = 0; k < 4; k++) {
5050 *iter2++ = (GLushort)(extractComponents[k]*65535);
5051 }
5052 break;
5053 case GL_UNSIGNED_INT_8_8_8_8_REV:
5054 extract8888rev(myswap_bytes,iter,extractComponents);
5055 for (k = 0; k < 4; k++) {
5056 *iter2++ = (GLushort)(extractComponents[k]*65535);
5057 }
5058 break;
5059 case GL_UNSIGNED_INT_10_10_10_2:
5060 extract1010102(myswap_bytes,iter,extractComponents);
5061 for (k = 0; k < 4; k++) {
5062 *iter2++ = (GLushort)(extractComponents[k]*65535);
5063 }
5064 break;
5065 case GL_UNSIGNED_INT_2_10_10_10_REV:
5066 extract2101010rev(myswap_bytes,iter,extractComponents);
5067 for (k = 0; k < 4; k++) {
5068 *iter2++ = (GLushort)(extractComponents[k]*65535);
5069 }
5070 break;
5071 case GL_INT:
5072 case GL_UNSIGNED_INT:
5073 case GL_FLOAT:
5074 if (myswap_bytes) {
5075 widget.ub[0] = iter[3];
5076 widget.ub[1] = iter[2];
5077 widget.ub[2] = iter[1];
5078 widget.ub[3] = iter[0];
5079 } else {
5080 widget.ub[0] = iter[0];
5081 widget.ub[1] = iter[1];
5082 widget.ub[2] = iter[2];
5083 widget.ub[3] = iter[3];
5084 }
5085 if (type == GL_FLOAT) {
5086 if (index_format) {
5087 *iter2++ = widget.f;
5088 } else {
5089 *iter2++ = 65535 * widget.f;
5090 }
5091 } else if (type == GL_UNSIGNED_INT) {
5092 if (index_format) {
5093 *iter2++ = widget.ui;
5094 } else {
5095 *iter2++ = widget.ui >> 16;
5096 }
5097 } else {
5098 if (index_format) {
5099 *iter2++ = widget.i;
5100 } else {
5101 *iter2++ = widget.i >> 15;
5102 }
5103 }
5104 break;
5105 }
5106 iter += element_size;
5107 } /* for j */
5108 start += rowsize;
5109 #if 1
5110 /* want 'iter' pointing at start, not within, row for assertion
5111 * purposes
5112 */
5113 iter= start;
5114 #endif
5115 } /* for i */
5116
5117 /* iterators should be one byte past end */
5118 if (!isTypePackedPixel(type)) {
5119 assert(iter2 == &newimage[width*height*components]);
5120 }
5121 else {
5122 assert(iter2 == &newimage[width*height*
5123 elements_per_group(format,0)]);
5124 }
5125 assert( iter == &((const GLubyte *)userdata)[rowsize*height +
5126 psm->unpack_skip_rows * rowsize +
5127 psm->unpack_skip_pixels * group_size] );
5128
5129 } /* else */
5130 } /* fill_image() */
5131
5132 /*
5133 ** Insert array into user's data applying all pixel store modes.
5134 ** The internal format is an array of unsigned shorts.
5135 ** empty_image() because it is the opposite of fill_image().
5136 */
5137 static void empty_image(const PixelStorageModes *psm,
5138 GLint width, GLint height, GLenum format,
5139 GLenum type, GLboolean index_format,
5140 const GLushort *oldimage, void *userdata)
5141 {
5142 GLint components;
5143 GLint element_size;
5144 GLint rowsize;
5145 GLint padding;
5146 GLint groups_per_line;
5147 GLint group_size;
5148 GLint elements_per_line;
5149 GLubyte *start;
5150 GLubyte *iter;
5151 const GLushort *iter2;
5152 GLint i, j, k;
5153 GLint myswap_bytes;
5154
5155 myswap_bytes = psm->pack_swap_bytes;
5156 components = elements_per_group(format,type);
5157 if (psm->pack_row_length > 0) {
5158 groups_per_line = psm->pack_row_length;
5159 } else {
5160 groups_per_line = width;
5161 }
5162
5163 /* All formats except GL_BITMAP fall out trivially */
5164 if (type == GL_BITMAP) {
5165 GLint bit_offset;
5166 GLint current_bit;
5167
5168 rowsize = (groups_per_line * components + 7) / 8;
5169 padding = (rowsize % psm->pack_alignment);
5170 if (padding) {
5171 rowsize += psm->pack_alignment - padding;
5172 }
5173 start = (GLubyte *) userdata + psm->pack_skip_rows * rowsize +
5174 (psm->pack_skip_pixels * components / 8);
5175 elements_per_line = width * components;
5176 iter2 = oldimage;
5177 for (i = 0; i < height; i++) {
5178 iter = start;
5179 bit_offset = (psm->pack_skip_pixels * components) % 8;
5180 for (j = 0; j < elements_per_line; j++) {
5181 if (index_format) {
5182 current_bit = iter2[0] & 1;
5183 } else {
5184 if (iter2[0] > 32767) {
5185 current_bit = 1;
5186 } else {
5187 current_bit = 0;
5188 }
5189 }
5190
5191 if (current_bit) {
5192 if (psm->pack_lsb_first) {
5193 *iter |= (1 << bit_offset);
5194 } else {
5195 *iter |= (1 << (7 - bit_offset));
5196 }
5197 } else {
5198 if (psm->pack_lsb_first) {
5199 *iter &= ~(1 << bit_offset);
5200 } else {
5201 *iter &= ~(1 << (7 - bit_offset));
5202 }
5203 }
5204
5205 bit_offset++;
5206 if (bit_offset == 8) {
5207 bit_offset = 0;
5208 iter++;
5209 }
5210 iter2++;
5211 }
5212 start += rowsize;
5213 }
5214 } else {
5215 float shoveComponents[4];
5216
5217 element_size = bytes_per_element(type);
5218 group_size = element_size * components;
5219 if (element_size == 1) myswap_bytes = 0;
5220
5221 rowsize = groups_per_line * group_size;
5222 padding = (rowsize % psm->pack_alignment);
5223 if (padding) {
5224 rowsize += psm->pack_alignment - padding;
5225 }
5226 start = (GLubyte *) userdata + psm->pack_skip_rows * rowsize +
5227 psm->pack_skip_pixels * group_size;
5228 elements_per_line = width * components;
5229
5230 iter2 = oldimage;
5231 for (i = 0; i < height; i++) {
5232 iter = start;
5233 for (j = 0; j < elements_per_line; j++) {
5234 Type_Widget widget;
5235
5236 switch(type) {
5237 case GL_UNSIGNED_BYTE_3_3_2:
5238 for (k = 0; k < 3; k++) {
5239 shoveComponents[k]= *iter2++ / 65535.0;
5240 }
5241 shove332(shoveComponents,0,(void *)iter);
5242 break;
5243 case GL_UNSIGNED_BYTE_2_3_3_REV:
5244 for (k = 0; k < 3; k++) {
5245 shoveComponents[k]= *iter2++ / 65535.0;
5246 }
5247 shove233rev(shoveComponents,0,(void *)iter);
5248 break;
5249 case GL_UNSIGNED_BYTE:
5250 if (index_format) {
5251 *iter = *iter2++;
5252 } else {
5253 *iter = *iter2++ >> 8;
5254 }
5255 break;
5256 case GL_BYTE:
5257 if (index_format) {
5258 *((GLbyte *) iter) = *iter2++;
5259 } else {
5260 *((GLbyte *) iter) = *iter2++ >> 9;
5261 }
5262 break;
5263 case GL_UNSIGNED_SHORT_5_6_5:
5264 for (k = 0; k < 3; k++) {
5265 shoveComponents[k]= *iter2++ / 65535.0;
5266 }
5267 shove565(shoveComponents,0,(void *)&widget.us[0]);
5268 if (myswap_bytes) {
5269 iter[0] = widget.ub[1];
5270 iter[1] = widget.ub[0];
5271 }
5272 else {
5273 *(GLushort *)iter = widget.us[0];
5274 }
5275 break;
5276 case GL_UNSIGNED_SHORT_5_6_5_REV:
5277 for (k = 0; k < 3; k++) {
5278 shoveComponents[k]= *iter2++ / 65535.0;
5279 }
5280 shove565rev(shoveComponents,0,(void *)&widget.us[0]);
5281 if (myswap_bytes) {
5282 iter[0] = widget.ub[1];
5283 iter[1] = widget.ub[0];
5284 }
5285 else {
5286 *(GLushort *)iter = widget.us[0];
5287 }
5288 break;
5289 case GL_UNSIGNED_SHORT_4_4_4_4:
5290 for (k = 0; k < 4; k++) {
5291 shoveComponents[k]= *iter2++ / 65535.0;
5292 }
5293 shove4444(shoveComponents,0,(void *)&widget.us[0]);
5294 if (myswap_bytes) {
5295 iter[0] = widget.ub[1];
5296 iter[1] = widget.ub[0];
5297 } else {
5298 *(GLushort *)iter = widget.us[0];
5299 }
5300 break;
5301 case GL_UNSIGNED_SHORT_4_4_4_4_REV:
5302 for (k = 0; k < 4; k++) {
5303 shoveComponents[k]= *iter2++ / 65535.0;
5304 }
5305 shove4444rev(shoveComponents,0,(void *)&widget.us[0]);
5306 if (myswap_bytes) {
5307 iter[0] = widget.ub[1];
5308 iter[1] = widget.ub[0];
5309 } else {
5310 *(GLushort *)iter = widget.us[0];
5311 }
5312 break;
5313 case GL_UNSIGNED_SHORT_5_5_5_1:
5314 for (k = 0; k < 4; k++) {
5315 shoveComponents[k]= *iter2++ / 65535.0;
5316 }
5317 shove5551(shoveComponents,0,(void *)&widget.us[0]);
5318 if (myswap_bytes) {
5319 iter[0] = widget.ub[1];
5320 iter[1] = widget.ub[0];
5321 } else {
5322 *(GLushort *)iter = widget.us[0];
5323 }
5324 break;
5325 case GL_UNSIGNED_SHORT_1_5_5_5_REV:
5326 for (k = 0; k < 4; k++) {
5327 shoveComponents[k]= *iter2++ / 65535.0;
5328 }
5329 shove1555rev(shoveComponents,0,(void *)&widget.us[0]);
5330 if (myswap_bytes) {
5331 iter[0] = widget.ub[1];
5332 iter[1] = widget.ub[0];
5333 } else {
5334 *(GLushort *)iter = widget.us[0];
5335 }
5336 break;
5337 case GL_UNSIGNED_SHORT:
5338 case GL_SHORT:
5339 if (type == GL_SHORT) {
5340 if (index_format) {
5341 widget.s[0] = *iter2++;
5342 } else {
5343 widget.s[0] = *iter2++ >> 1;
5344 }
5345 } else {
5346 widget.us[0] = *iter2++;
5347 }
5348 if (myswap_bytes) {
5349 iter[0] = widget.ub[1];
5350 iter[1] = widget.ub[0];
5351 } else {
5352 iter[0] = widget.ub[0];
5353 iter[1] = widget.ub[1];
5354 }
5355 break;
5356 case GL_UNSIGNED_INT_8_8_8_8:
5357 for (k = 0; k < 4; k++) {
5358 shoveComponents[k]= *iter2++ / 65535.0;
5359 }
5360 shove8888(shoveComponents,0,(void *)&widget.ui);
5361 if (myswap_bytes) {
5362 iter[3] = widget.ub[0];
5363 iter[2] = widget.ub[1];
5364 iter[1] = widget.ub[2];
5365 iter[0] = widget.ub[3];
5366 } else {
5367 *(GLuint *)iter= widget.ui;
5368 }
5369
5370 break;
5371 case GL_UNSIGNED_INT_8_8_8_8_REV:
5372 for (k = 0; k < 4; k++) {
5373 shoveComponents[k]= *iter2++ / 65535.0;
5374 }
5375 shove8888rev(shoveComponents,0,(void *)&widget.ui);
5376 if (myswap_bytes) {
5377 iter[3] = widget.ub[0];
5378 iter[2] = widget.ub[1];
5379 iter[1] = widget.ub[2];
5380 iter[0] = widget.ub[3];
5381 } else {
5382 *(GLuint *)iter= widget.ui;
5383 }
5384 break;
5385 case GL_UNSIGNED_INT_10_10_10_2:
5386 for (k = 0; k < 4; k++) {
5387 shoveComponents[k]= *iter2++ / 65535.0;
5388 }
5389 shove1010102(shoveComponents,0,(void *)&widget.ui);
5390 if (myswap_bytes) {
5391 iter[3] = widget.ub[0];
5392 iter[2] = widget.ub[1];
5393 iter[1] = widget.ub[2];
5394 iter[0] = widget.ub[3];
5395 } else {
5396 *(GLuint *)iter= widget.ui;
5397 }
5398 break;
5399 case GL_UNSIGNED_INT_2_10_10_10_REV:
5400 for (k = 0; k < 4; k++) {
5401 shoveComponents[k]= *iter2++ / 65535.0;
5402 }
5403 shove2101010rev(shoveComponents,0,(void *)&widget.ui);
5404 if (myswap_bytes) {
5405 iter[3] = widget.ub[0];
5406 iter[2] = widget.ub[1];
5407 iter[1] = widget.ub[2];
5408 iter[0] = widget.ub[3];
5409 } else {
5410 *(GLuint *)iter= widget.ui;
5411 }
5412 break;
5413 case GL_INT:
5414 case GL_UNSIGNED_INT:
5415 case GL_FLOAT:
5416 if (type == GL_FLOAT) {
5417 if (index_format) {
5418 widget.f = *iter2++;
5419 } else {
5420 widget.f = *iter2++ / (float) 65535.0;
5421 }
5422 } else if (type == GL_UNSIGNED_INT) {
5423 if (index_format) {
5424 widget.ui = *iter2++;
5425 } else {
5426 widget.ui = (unsigned int) *iter2++ * 65537;
5427 }
5428 } else {
5429 if (index_format) {
5430 widget.i = *iter2++;
5431 } else {
5432 widget.i = ((unsigned int) *iter2++ * 65537)/2;
5433 }
5434 }
5435 if (myswap_bytes) {
5436 iter[3] = widget.ub[0];
5437 iter[2] = widget.ub[1];
5438 iter[1] = widget.ub[2];
5439 iter[0] = widget.ub[3];
5440 } else {
5441 iter[0] = widget.ub[0];
5442 iter[1] = widget.ub[1];
5443 iter[2] = widget.ub[2];
5444 iter[3] = widget.ub[3];
5445 }
5446 break;
5447 }
5448 iter += element_size;
5449 } /* for j */
5450 start += rowsize;
5451 #if 1
5452 /* want 'iter' pointing at start, not within, row for assertion
5453 * purposes
5454 */
5455 iter= start;
5456 #endif
5457 } /* for i */
5458
5459 /* iterators should be one byte past end */
5460 if (!isTypePackedPixel(type)) {
5461 assert(iter2 == &oldimage[width*height*components]);
5462 }
5463 else {
5464 assert(iter2 == &oldimage[width*height*
5465 elements_per_group(format,0)]);
5466 }
5467 assert( iter == &((GLubyte *)userdata)[rowsize*height +
5468 psm->pack_skip_rows * rowsize +
5469 psm->pack_skip_pixels * group_size] );
5470
5471 } /* else */
5472 } /* empty_image() */
5473
5474 /*--------------------------------------------------------------------------
5475 * Decimation of packed pixel types
5476 *--------------------------------------------------------------------------
5477 */
5478 static void extract332(int isSwap,
5479 const void *packedPixel, GLfloat extractComponents[])
5480 {
5481 GLubyte ubyte= *(const GLubyte *)packedPixel;
5482
5483 isSwap= isSwap; /* turn off warnings */
5484
5485 /* 11100000 == 0xe0 */
5486 /* 00011100 == 0x1c */
5487 /* 00000011 == 0x03 */
5488
5489 extractComponents[0]= (float)((ubyte & 0xe0) >> 5) / 7.0;
5490 extractComponents[1]= (float)((ubyte & 0x1c) >> 2) / 7.0; /* 7 = 2^3-1 */
5491 extractComponents[2]= (float)((ubyte & 0x03) ) / 3.0; /* 3 = 2^2-1 */
5492 } /* extract332() */
5493
5494 static void shove332(const GLfloat shoveComponents[],
5495 int index, void *packedPixel)
5496 {
5497 /* 11100000 == 0xe0 */
5498 /* 00011100 == 0x1c */
5499 /* 00000011 == 0x03 */
5500
5501 assert(0.0 <= shoveComponents[0] && shoveComponents[0] <= 1.0);
5502 assert(0.0 <= shoveComponents[1] && shoveComponents[1] <= 1.0);
5503 assert(0.0 <= shoveComponents[2] && shoveComponents[2] <= 1.0);
5504
5505 /* due to limited precision, need to round before shoving */
5506 ((GLubyte *)packedPixel)[index] =
5507 ((GLubyte)((shoveComponents[0] * 7)+0.5) << 5) & 0xe0;
5508 ((GLubyte *)packedPixel)[index] |=
5509 ((GLubyte)((shoveComponents[1] * 7)+0.5) << 2) & 0x1c;
5510 ((GLubyte *)packedPixel)[index] |=
5511 ((GLubyte)((shoveComponents[2] * 3)+0.5) ) & 0x03;
5512 } /* shove332() */
5513
5514 static void extract233rev(int isSwap,
5515 const void *packedPixel, GLfloat extractComponents[])
5516 {
5517 GLubyte ubyte= *(const GLubyte *)packedPixel;
5518
5519 isSwap= isSwap; /* turn off warnings */
5520
5521 /* 0000,0111 == 0x07 */
5522 /* 0011,1000 == 0x38 */
5523 /* 1100,0000 == 0xC0 */
5524
5525 extractComponents[0]= (float)((ubyte & 0x07) ) / 7.0;
5526 extractComponents[1]= (float)((ubyte & 0x38) >> 3) / 7.0;
5527 extractComponents[2]= (float)((ubyte & 0xC0) >> 6) / 3.0;
5528 } /* extract233rev() */
5529
5530 static void shove233rev(const GLfloat shoveComponents[],
5531 int index, void *packedPixel)
5532 {
5533 /* 0000,0111 == 0x07 */
5534 /* 0011,1000 == 0x38 */
5535 /* 1100,0000 == 0xC0 */
5536
5537 assert(0.0 <= shoveComponents[0] && shoveComponents[0] <= 1.0);
5538 assert(0.0 <= shoveComponents[1] && shoveComponents[1] <= 1.0);
5539 assert(0.0 <= shoveComponents[2] && shoveComponents[2] <= 1.0);
5540
5541 /* due to limited precision, need to round before shoving */
5542 ((GLubyte *)packedPixel)[index] =
5543 ((GLubyte)((shoveComponents[0] * 7.0)+0.5) ) & 0x07;
5544 ((GLubyte *)packedPixel)[index]|=
5545 ((GLubyte)((shoveComponents[1] * 7.0)+0.5) << 3) & 0x38;
5546 ((GLubyte *)packedPixel)[index]|=
5547 ((GLubyte)((shoveComponents[2] * 3.0)+0.5) << 6) & 0xC0;
5548 } /* shove233rev() */
5549
5550 static void extract565(int isSwap,
5551 const void *packedPixel, GLfloat extractComponents[])
5552 {
5553 GLushort ushort= *(const GLushort *)packedPixel;
5554
5555 if (isSwap) {
5556 ushort= __GLU_SWAP_2_BYTES(packedPixel);
5557 }
5558 else {
5559 ushort= *(const GLushort *)packedPixel;
5560 }
5561
5562 /* 11111000,00000000 == 0xf800 */
5563 /* 00000111,11100000 == 0x07e0 */
5564 /* 00000000,00011111 == 0x001f */
5565
5566 extractComponents[0]=(float)((ushort & 0xf800) >> 11) / 31.0;/* 31 = 2^5-1*/
5567 extractComponents[1]=(float)((ushort & 0x07e0) >> 5) / 63.0;/* 63 = 2^6-1*/
5568 extractComponents[2]=(float)((ushort & 0x001f) ) / 31.0;
5569 } /* extract565() */
5570
5571 static void shove565(const GLfloat shoveComponents[],
5572 int index,void *packedPixel)
5573 {
5574 /* 11111000,00000000 == 0xf800 */
5575 /* 00000111,11100000 == 0x07e0 */
5576 /* 00000000,00011111 == 0x001f */
5577
5578 assert(0.0 <= shoveComponents[0] && shoveComponents[0] <= 1.0);
5579 assert(0.0 <= shoveComponents[1] && shoveComponents[1] <= 1.0);
5580 assert(0.0 <= shoveComponents[2] && shoveComponents[2] <= 1.0);
5581
5582 /* due to limited precision, need to round before shoving */
5583 ((GLushort *)packedPixel)[index] =
5584 ((GLushort)((shoveComponents[0] * 31)+0.5) << 11) & 0xf800;
5585 ((GLushort *)packedPixel)[index]|=
5586 ((GLushort)((shoveComponents[1] * 63)+0.5) << 5) & 0x07e0;
5587 ((GLushort *)packedPixel)[index]|=
5588 ((GLushort)((shoveComponents[2] * 31)+0.5) ) & 0x001f;
5589 } /* shove565() */
5590
5591 static void extract565rev(int isSwap,
5592 const void *packedPixel, GLfloat extractComponents[])
5593 {
5594 GLushort ushort= *(const GLushort *)packedPixel;
5595
5596 if (isSwap) {
5597 ushort= __GLU_SWAP_2_BYTES(packedPixel);
5598 }
5599 else {
5600 ushort= *(const GLushort *)packedPixel;
5601 }
5602
5603 /* 00000000,00011111 == 0x001f */
5604 /* 00000111,11100000 == 0x07e0 */
5605 /* 11111000,00000000 == 0xf800 */
5606
5607 extractComponents[0]= (float)((ushort & 0x001F) ) / 31.0;
5608 extractComponents[1]= (float)((ushort & 0x07E0) >> 5) / 63.0;
5609 extractComponents[2]= (float)((ushort & 0xF800) >> 11) / 31.0;
5610 } /* extract565rev() */
5611
5612 static void shove565rev(const GLfloat shoveComponents[],
5613 int index,void *packedPixel)
5614 {
5615 /* 00000000,00011111 == 0x001f */
5616 /* 00000111,11100000 == 0x07e0 */
5617 /* 11111000,00000000 == 0xf800 */
5618
5619 assert(0.0 <= shoveComponents[0] && shoveComponents[0] <= 1.0);
5620 assert(0.0 <= shoveComponents[1] && shoveComponents[1] <= 1.0);
5621 assert(0.0 <= shoveComponents[2] && shoveComponents[2] <= 1.0);
5622
5623 /* due to limited precision, need to round before shoving */
5624 ((GLushort *)packedPixel)[index] =
5625 ((GLushort)((shoveComponents[0] * 31.0)+0.5) ) & 0x001F;
5626 ((GLushort *)packedPixel)[index]|=
5627 ((GLushort)((shoveComponents[1] * 63.0)+0.5) << 5) & 0x07E0;
5628 ((GLushort *)packedPixel)[index]|=
5629 ((GLushort)((shoveComponents[2] * 31.0)+0.5) << 11) & 0xF800;
5630 } /* shove565rev() */
5631
5632 static void extract4444(int isSwap,const void *packedPixel,
5633 GLfloat extractComponents[])
5634 {
5635 GLushort ushort;
5636
5637 if (isSwap) {
5638 ushort= __GLU_SWAP_2_BYTES(packedPixel);
5639 }
5640 else {
5641 ushort= *(const GLushort *)packedPixel;
5642 }
5643
5644 /* 11110000,00000000 == 0xf000 */
5645 /* 00001111,00000000 == 0x0f00 */
5646 /* 00000000,11110000 == 0x00f0 */
5647 /* 00000000,00001111 == 0x000f */
5648
5649 extractComponents[0]= (float)((ushort & 0xf000) >> 12) / 15.0;/* 15=2^4-1 */
5650 extractComponents[1]= (float)((ushort & 0x0f00) >> 8) / 15.0;
5651 extractComponents[2]= (float)((ushort & 0x00f0) >> 4) / 15.0;
5652 extractComponents[3]= (float)((ushort & 0x000f) ) / 15.0;
5653 } /* extract4444() */
5654
5655 static void shove4444(const GLfloat shoveComponents[],
5656 int index,void *packedPixel)
5657 {
5658 assert(0.0 <= shoveComponents[0] && shoveComponents[0] <= 1.0);
5659 assert(0.0 <= shoveComponents[1] && shoveComponents[1] <= 1.0);
5660 assert(0.0 <= shoveComponents[2] && shoveComponents[2] <= 1.0);
5661 assert(0.0 <= shoveComponents[3] && shoveComponents[3] <= 1.0);
5662
5663 /* due to limited precision, need to round before shoving */
5664 ((GLushort *)packedPixel)[index] =
5665 ((GLushort)((shoveComponents[0] * 15)+0.5) << 12) & 0xf000;
5666 ((GLushort *)packedPixel)[index]|=
5667 ((GLushort)((shoveComponents[1] * 15)+0.5) << 8) & 0x0f00;
5668 ((GLushort *)packedPixel)[index]|=
5669 ((GLushort)((shoveComponents[2] * 15)+0.5) << 4) & 0x00f0;
5670 ((GLushort *)packedPixel)[index]|=
5671 ((GLushort)((shoveComponents[3] * 15)+0.5) ) & 0x000f;
5672 } /* shove4444() */
5673
5674 static void extract4444rev(int isSwap,const void *packedPixel,
5675 GLfloat extractComponents[])
5676 {
5677 GLushort ushort;
5678
5679 if (isSwap) {
5680 ushort= __GLU_SWAP_2_BYTES(packedPixel);
5681 }
5682 else {
5683 ushort= *(const GLushort *)packedPixel;
5684 }
5685
5686 /* 00000000,00001111 == 0x000f */
5687 /* 00000000,11110000 == 0x00f0 */
5688 /* 00001111,00000000 == 0x0f00 */
5689 /* 11110000,00000000 == 0xf000 */
5690
5691 /* 15 = 2^4-1 */
5692 extractComponents[0]= (float)((ushort & 0x000F) ) / 15.0;
5693 extractComponents[1]= (float)((ushort & 0x00F0) >> 4) / 15.0;
5694 extractComponents[2]= (float)((ushort & 0x0F00) >> 8) / 15.0;
5695 extractComponents[3]= (float)((ushort & 0xF000) >> 12) / 15.0;
5696 } /* extract4444rev() */
5697
5698 static void shove4444rev(const GLfloat shoveComponents[],
5699 int index,void *packedPixel)
5700 {
5701 /* 00000000,00001111 == 0x000f */
5702 /* 00000000,11110000 == 0x00f0 */
5703 /* 00001111,00000000 == 0x0f00 */
5704 /* 11110000,00000000 == 0xf000 */
5705
5706 assert(0.0 <= shoveComponents[0] && shoveComponents[0] <= 1.0);
5707 assert(0.0 <= shoveComponents[1] && shoveComponents[1] <= 1.0);
5708 assert(0.0 <= shoveComponents[2] && shoveComponents[2] <= 1.0);
5709 assert(0.0 <= shoveComponents[3] && shoveComponents[3] <= 1.0);
5710
5711 /* due to limited precision, need to round before shoving */
5712 ((GLushort *)packedPixel)[index] =
5713 ((GLushort)((shoveComponents[0] * 15)+0.5) ) & 0x000F;
5714 ((GLushort *)packedPixel)[index]|=
5715 ((GLushort)((shoveComponents[1] * 15)+0.5) << 4) & 0x00F0;
5716 ((GLushort *)packedPixel)[index]|=
5717 ((GLushort)((shoveComponents[2] * 15)+0.5) << 8) & 0x0F00;
5718 ((GLushort *)packedPixel)[index]|=
5719 ((GLushort)((shoveComponents[3] * 15)+0.5) << 12) & 0xF000;
5720 } /* shove4444rev() */
5721
5722 static void extract5551(int isSwap,const void *packedPixel,
5723 GLfloat extractComponents[])
5724 {
5725 GLushort ushort;
5726
5727 if (isSwap) {
5728 ushort= __GLU_SWAP_2_BYTES(packedPixel);
5729 }
5730 else {
5731 ushort= *(const GLushort *)packedPixel;
5732 }
5733
5734 /* 11111000,00000000 == 0xf800 */
5735 /* 00000111,11000000 == 0x07c0 */
5736 /* 00000000,00111110 == 0x003e */
5737 /* 00000000,00000001 == 0x0001 */
5738
5739 extractComponents[0]=(float)((ushort & 0xf800) >> 11) / 31.0;/* 31 = 2^5-1*/
5740 extractComponents[1]=(float)((ushort & 0x07c0) >> 6) / 31.0;
5741 extractComponents[2]=(float)((ushort & 0x003e) >> 1) / 31.0;
5742 extractComponents[3]=(float)((ushort & 0x0001) );
5743 } /* extract5551() */
5744
5745 static void shove5551(const GLfloat shoveComponents[],
5746 int index,void *packedPixel)
5747 {
5748 /* 11111000,00000000 == 0xf800 */
5749 /* 00000111,11000000 == 0x07c0 */
5750 /* 00000000,00111110 == 0x003e */
5751 /* 00000000,00000001 == 0x0001 */
5752
5753 assert(0.0 <= shoveComponents[0] && shoveComponents[0] <= 1.0);
5754 assert(0.0 <= shoveComponents[1] && shoveComponents[1] <= 1.0);
5755 assert(0.0 <= shoveComponents[2] && shoveComponents[2] <= 1.0);
5756 assert(0.0 <= shoveComponents[3] && shoveComponents[3] <= 1.0);
5757
5758 /* due to limited precision, need to round before shoving */
5759 ((GLushort *)packedPixel)[index] =
5760 ((GLushort)((shoveComponents[0] * 31)+0.5) << 11) & 0xf800;
5761 ((GLushort *)packedPixel)[index]|=
5762 ((GLushort)((shoveComponents[1] * 31)+0.5) << 6) & 0x07c0;
5763 ((GLushort *)packedPixel)[index]|=
5764 ((GLushort)((shoveComponents[2] * 31)+0.5) << 1) & 0x003e;
5765 ((GLushort *)packedPixel)[index]|=
5766 ((GLushort)((shoveComponents[3])+0.5) ) & 0x0001;
5767 } /* shove5551() */
5768
5769 static void extract1555rev(int isSwap,const void *packedPixel,
5770 GLfloat extractComponents[])
5771 {
5772 GLushort ushort;
5773
5774 if (isSwap) {
5775 ushort= __GLU_SWAP_2_BYTES(packedPixel);
5776 }
5777 else {
5778 ushort= *(const GLushort *)packedPixel;
5779 }
5780
5781 /* 00000000,00011111 == 0x001F */
5782 /* 00000011,11100000 == 0x03E0 */
5783 /* 01111100,00000000 == 0x7C00 */
5784 /* 10000000,00000000 == 0x8000 */
5785
5786 /* 31 = 2^5-1 */
5787 extractComponents[0]= (float)((ushort & 0x001F) ) / 31.0;
5788 extractComponents[1]= (float)((ushort & 0x03E0) >> 5) / 31.0;
5789 extractComponents[2]= (float)((ushort & 0x7C00) >> 10) / 31.0;
5790 extractComponents[3]= (float)((ushort & 0x8000) >> 15);
5791 } /* extract1555rev() */
5792
5793 static void shove1555rev(const GLfloat shoveComponents[],
5794 int index,void *packedPixel)
5795 {
5796 /* 00000000,00011111 == 0x001F */
5797 /* 00000011,11100000 == 0x03E0 */
5798 /* 01111100,00000000 == 0x7C00 */
5799 /* 10000000,00000000 == 0x8000 */
5800
5801 assert(0.0 <= shoveComponents[0] && shoveComponents[0] <= 1.0);
5802 assert(0.0 <= shoveComponents[1] && shoveComponents[1] <= 1.0);
5803 assert(0.0 <= shoveComponents[2] && shoveComponents[2] <= 1.0);
5804 assert(0.0 <= shoveComponents[3] && shoveComponents[3] <= 1.0);
5805
5806 /* due to limited precision, need to round before shoving */
5807 ((GLushort *)packedPixel)[index] =
5808 ((GLushort)((shoveComponents[0] * 31)+0.5) ) & 0x001F;
5809 ((GLushort *)packedPixel)[index]|=
5810 ((GLushort)((shoveComponents[1] * 31)+0.5) << 5) & 0x03E0;
5811 ((GLushort *)packedPixel)[index]|=
5812 ((GLushort)((shoveComponents[2] * 31)+0.5) << 10) & 0x7C00;
5813 ((GLushort *)packedPixel)[index]|=
5814 ((GLushort)((shoveComponents[3])+0.5) << 15) & 0x8000;
5815 } /* shove1555rev() */
5816
5817 static void extract8888(int isSwap,
5818 const void *packedPixel, GLfloat extractComponents[])
5819 {
5820 GLuint uint;
5821
5822 if (isSwap) {
5823 uint= __GLU_SWAP_4_BYTES(packedPixel);
5824 }
5825 else {
5826 uint= *(const GLuint *)packedPixel;
5827 }
5828
5829 /* 11111111,00000000,00000000,00000000 == 0xff000000 */
5830 /* 00000000,11111111,00000000,00000000 == 0x00ff0000 */
5831 /* 00000000,00000000,11111111,00000000 == 0x0000ff00 */
5832 /* 00000000,00000000,00000000,11111111 == 0x000000ff */
5833
5834 /* 255 = 2^8-1 */
5835 extractComponents[0]= (float)((uint & 0xff000000) >> 24) / 255.0;
5836 extractComponents[1]= (float)((uint & 0x00ff0000) >> 16) / 255.0;
5837 extractComponents[2]= (float)((uint & 0x0000ff00) >> 8) / 255.0;
5838 extractComponents[3]= (float)((uint & 0x000000ff) ) / 255.0;
5839 } /* extract8888() */
5840
5841 static void shove8888(const GLfloat shoveComponents[],
5842 int index,void *packedPixel)
5843 {
5844 /* 11111111,00000000,00000000,00000000 == 0xff000000 */
5845 /* 00000000,11111111,00000000,00000000 == 0x00ff0000 */
5846 /* 00000000,00000000,11111111,00000000 == 0x0000ff00 */
5847 /* 00000000,00000000,00000000,11111111 == 0x000000ff */
5848
5849 assert(0.0 <= shoveComponents[0] && shoveComponents[0] <= 1.0);
5850 assert(0.0 <= shoveComponents[1] && shoveComponents[1] <= 1.0);
5851 assert(0.0 <= shoveComponents[2] && shoveComponents[2] <= 1.0);
5852 assert(0.0 <= shoveComponents[3] && shoveComponents[3] <= 1.0);
5853
5854 /* due to limited precision, need to round before shoving */
5855 ((GLuint *)packedPixel)[index] =
5856 ((GLuint)((shoveComponents[0] * 255)+0.5) << 24) & 0xff000000;
5857 ((GLuint *)packedPixel)[index]|=
5858 ((GLuint)((shoveComponents[1] * 255)+0.5) << 16) & 0x00ff0000;
5859 ((GLuint *)packedPixel)[index]|=
5860 ((GLuint)((shoveComponents[2] * 255)+0.5) << 8) & 0x0000ff00;
5861 ((GLuint *)packedPixel)[index]|=
5862 ((GLuint)((shoveComponents[3] * 255)+0.5) ) & 0x000000ff;
5863 } /* shove8888() */
5864
5865 static void extract8888rev(int isSwap,
5866 const void *packedPixel,GLfloat extractComponents[])
5867 {
5868 GLuint uint;
5869
5870 if (isSwap) {
5871 uint= __GLU_SWAP_4_BYTES(packedPixel);
5872 }
5873 else {
5874 uint= *(const GLuint *)packedPixel;
5875 }
5876
5877 /* 00000000,00000000,00000000,11111111 == 0x000000ff */
5878 /* 00000000,00000000,11111111,00000000 == 0x0000ff00 */
5879 /* 00000000,11111111,00000000,00000000 == 0x00ff0000 */
5880 /* 11111111,00000000,00000000,00000000 == 0xff000000 */
5881
5882 /* 255 = 2^8-1 */
5883 extractComponents[0]= (float)((uint & 0x000000FF) ) / 255.0;
5884 extractComponents[1]= (float)((uint & 0x0000FF00) >> 8) / 255.0;
5885 extractComponents[2]= (float)((uint & 0x00FF0000) >> 16) / 255.0;
5886 extractComponents[3]= (float)((uint & 0xFF000000) >> 24) / 255.0;
5887 } /* extract8888rev() */
5888
5889 static void shove8888rev(const GLfloat shoveComponents[],
5890 int index,void *packedPixel)
5891 {
5892 /* 00000000,00000000,00000000,11111111 == 0x000000ff */
5893 /* 00000000,00000000,11111111,00000000 == 0x0000ff00 */
5894 /* 00000000,11111111,00000000,00000000 == 0x00ff0000 */
5895 /* 11111111,00000000,00000000,00000000 == 0xff000000 */
5896
5897 assert(0.0 <= shoveComponents[0] && shoveComponents[0] <= 1.0);
5898 assert(0.0 <= shoveComponents[1] && shoveComponents[1] <= 1.0);
5899 assert(0.0 <= shoveComponents[2] && shoveComponents[2] <= 1.0);
5900 assert(0.0 <= shoveComponents[3] && shoveComponents[3] <= 1.0);
5901
5902 /* due to limited precision, need to round before shoving */
5903 ((GLuint *)packedPixel)[index] =
5904 ((GLuint)((shoveComponents[0] * 255)+0.5) ) & 0x000000FF;
5905 ((GLuint *)packedPixel)[index]|=
5906 ((GLuint)((shoveComponents[1] * 255)+0.5) << 8) & 0x0000FF00;
5907 ((GLuint *)packedPixel)[index]|=
5908 ((GLuint)((shoveComponents[2] * 255)+0.5) << 16) & 0x00FF0000;
5909 ((GLuint *)packedPixel)[index]|=
5910 ((GLuint)((shoveComponents[3] * 255)+0.5) << 24) & 0xFF000000;
5911 } /* shove8888rev() */
5912
5913 static void extract1010102(int isSwap,
5914 const void *packedPixel,GLfloat extractComponents[])
5915 {
5916 GLuint uint;
5917
5918 if (isSwap) {
5919 uint= __GLU_SWAP_4_BYTES(packedPixel);
5920 }
5921 else {
5922 uint= *(const GLuint *)packedPixel;
5923 }
5924
5925 /* 11111111,11000000,00000000,00000000 == 0xffc00000 */
5926 /* 00000000,00111111,11110000,00000000 == 0x003ff000 */
5927 /* 00000000,00000000,00001111,11111100 == 0x00000ffc */
5928 /* 00000000,00000000,00000000,00000011 == 0x00000003 */
5929
5930 /* 1023 = 2^10-1 */
5931 extractComponents[0]= (float)((uint & 0xffc00000) >> 22) / 1023.0;
5932 extractComponents[1]= (float)((uint & 0x003ff000) >> 12) / 1023.0;
5933 extractComponents[2]= (float)((uint & 0x00000ffc) >> 2) / 1023.0;
5934 extractComponents[3]= (float)((uint & 0x00000003) ) / 3.0;
5935 } /* extract1010102() */
5936
5937 static void shove1010102(const GLfloat shoveComponents[],
5938 int index,void *packedPixel)
5939 {
5940 /* 11111111,11000000,00000000,00000000 == 0xffc00000 */
5941 /* 00000000,00111111,11110000,00000000 == 0x003ff000 */
5942 /* 00000000,00000000,00001111,11111100 == 0x00000ffc */
5943 /* 00000000,00000000,00000000,00000011 == 0x00000003 */
5944
5945 assert(0.0 <= shoveComponents[0] && shoveComponents[0] <= 1.0);
5946 assert(0.0 <= shoveComponents[1] && shoveComponents[1] <= 1.0);
5947 assert(0.0 <= shoveComponents[2] && shoveComponents[2] <= 1.0);
5948 assert(0.0 <= shoveComponents[3] && shoveComponents[3] <= 1.0);
5949
5950 /* due to limited precision, need to round before shoving */
5951 ((GLuint *)packedPixel)[index] =
5952 ((GLuint)((shoveComponents[0] * 1023)+0.5) << 22) & 0xffc00000;
5953 ((GLuint *)packedPixel)[index]|=
5954 ((GLuint)((shoveComponents[1] * 1023)+0.5) << 12) & 0x003ff000;
5955 ((GLuint *)packedPixel)[index]|=
5956 ((GLuint)((shoveComponents[2] * 1023)+0.5) << 2) & 0x00000ffc;
5957 ((GLuint *)packedPixel)[index]|=
5958 ((GLuint)((shoveComponents[3] * 3)+0.5) ) & 0x00000003;
5959 } /* shove1010102() */
5960
5961 static void extract2101010rev(int isSwap,
5962 const void *packedPixel,
5963 GLfloat extractComponents[])
5964 {
5965 GLuint uint;
5966
5967 if (isSwap) {
5968 uint= __GLU_SWAP_4_BYTES(packedPixel);
5969 }
5970 else {
5971 uint= *(const GLuint *)packedPixel;
5972 }
5973
5974 /* 00000000,00000000,00000011,11111111 == 0x000003FF */
5975 /* 00000000,00001111,11111100,00000000 == 0x000FFC00 */
5976 /* 00111111,11110000,00000000,00000000 == 0x3FF00000 */
5977 /* 11000000,00000000,00000000,00000000 == 0xC0000000 */
5978
5979 /* 1023 = 2^10-1 */
5980 extractComponents[0]= (float)((uint & 0x000003FF) ) / 1023.0;
5981 extractComponents[1]= (float)((uint & 0x000FFC00) >> 10) / 1023.0;
5982 extractComponents[2]= (float)((uint & 0x3FF00000) >> 20) / 1023.0;
5983 extractComponents[3]= (float)((uint & 0xC0000000) >> 30) / 3.0;
5984 /* 3 = 2^2-1 */
5985 } /* extract2101010rev() */
5986
5987 static void shove2101010rev(const GLfloat shoveComponents[],
5988 int index,void *packedPixel)
5989 {
5990 /* 00000000,00000000,00000011,11111111 == 0x000003FF */
5991 /* 00000000,00001111,11111100,00000000 == 0x000FFC00 */
5992 /* 00111111,11110000,00000000,00000000 == 0x3FF00000 */
5993 /* 11000000,00000000,00000000,00000000 == 0xC0000000 */
5994
5995 assert(0.0 <= shoveComponents[0] && shoveComponents[0] <= 1.0);
5996 assert(0.0 <= shoveComponents[1] && shoveComponents[1] <= 1.0);
5997 assert(0.0 <= shoveComponents[2] && shoveComponents[2] <= 1.0);
5998 assert(0.0 <= shoveComponents[3] && shoveComponents[3] <= 1.0);
5999
6000 /* due to limited precision, need to round before shoving */
6001 ((GLuint *)packedPixel)[index] =
6002 ((GLuint)((shoveComponents[0] * 1023)+0.5) ) & 0x000003FF;
6003 ((GLuint *)packedPixel)[index]|=
6004 ((GLuint)((shoveComponents[1] * 1023)+0.5) << 10) & 0x000FFC00;
6005 ((GLuint *)packedPixel)[index]|=
6006 ((GLuint)((shoveComponents[2] * 1023)+0.5) << 20) & 0x3FF00000;
6007 ((GLuint *)packedPixel)[index]|=
6008 ((GLuint)((shoveComponents[3] * 3)+0.5) << 30) & 0xC0000000;
6009 } /* shove2101010rev() */
6010
6011 static void scaleInternalPackedPixel(int components,
6012 void (*extractPackedPixel)
6013 (int, const void *,GLfloat []),
6014 void (*shovePackedPixel)
6015 (const GLfloat [], int, void *),
6016 GLint widthIn,GLint heightIn,
6017 const void *dataIn,
6018 GLint widthOut,GLint heightOut,
6019 void *dataOut,
6020 GLint pixelSizeInBytes,
6021 GLint rowSizeInBytes,GLint isSwap)
6022 {
6023 float convx;
6024 float convy;
6025 float percent;
6026
6027 /* Max components in a format is 4, so... */
6028 float totals[4];
6029 float extractTotals[4], extractMoreTotals[4], shoveTotals[4];
6030
6031 float area;
6032 int i,j,k,xindex;
6033
6034 const char *temp, *temp0;
6035 int outindex;
6036
6037 int lowx_int, highx_int, lowy_int, highy_int;
6038 float x_percent, y_percent;
6039 float lowx_float, highx_float, lowy_float, highy_float;
6040 float convy_float, convx_float;
6041 int convy_int, convx_int;
6042 int l, m;
6043 const char *left, *right;
6044
6045 if (widthIn == widthOut*2 && heightIn == heightOut*2) {
6046 halveImagePackedPixel(components,extractPackedPixel,shovePackedPixel,
6047 widthIn, heightIn, dataIn, dataOut,
6048 pixelSizeInBytes,rowSizeInBytes,isSwap);
6049 return;
6050 }
6051 convy = (float) heightIn/heightOut;
6052 convx = (float) widthIn/widthOut;
6053 convy_int = floor(convy);
6054 convy_float = convy - convy_int;
6055 convx_int = floor(convx);
6056 convx_float = convx - convx_int;
6057
6058 area = convx * convy;
6059
6060 lowy_int = 0;
6061 lowy_float = 0;
6062 highy_int = convy_int;
6063 highy_float = convy_float;
6064
6065 for (i = 0; i < heightOut; i++) {
6066 lowx_int = 0;
6067 lowx_float = 0;
6068 highx_int = convx_int;
6069 highx_float = convx_float;
6070
6071 for (j = 0; j < widthOut; j++) {
6072 /*
6073 ** Ok, now apply box filter to box that goes from (lowx, lowy)
6074 ** to (highx, highy) on input data into this pixel on output
6075 ** data.
6076 */
6077 totals[0] = totals[1] = totals[2] = totals[3] = 0.0;
6078
6079 /* calculate the value for pixels in the 1st row */
6080 xindex = lowx_int*pixelSizeInBytes;
6081 if((highy_int>lowy_int) && (highx_int>lowx_int)) {
6082
6083 y_percent = 1-lowy_float;
6084 temp = (const char *)dataIn + xindex + lowy_int * rowSizeInBytes;
6085 percent = y_percent * (1-lowx_float);
6086 #if 0
6087 for (k = 0, temp_index = temp; k < components;
6088 k++, temp_index += element_size) {
6089 if (myswap_bytes) {
6090 totals[k] += __GLU_SWAP_2_BYTES(temp_index) * percent;
6091 } else {
6092 totals[k] += *(const GLushort*)temp_index * percent;
6093 }
6094 }
6095 #else
6096 (*extractPackedPixel)(isSwap,temp,extractTotals);
6097 for (k = 0; k < components; k++) {
6098 totals[k]+= extractTotals[k] * percent;
6099 }
6100 #endif
6101 left = temp;
6102 for(l = lowx_int+1; l < highx_int; l++) {
6103 temp += pixelSizeInBytes;
6104 #if 0
6105 for (k = 0, temp_index = temp; k < components;
6106 k++, temp_index += element_size) {
6107 if (myswap_bytes) {
6108 totals[k] +=
6109 __GLU_SWAP_2_BYTES(temp_index) * y_percent;
6110 } else {
6111 totals[k] += *(const GLushort*)temp_index * y_percent;
6112 }
6113 }
6114 #else
6115 (*extractPackedPixel)(isSwap,temp,extractTotals);
6116 for (k = 0; k < components; k++) {
6117 totals[k]+= extractTotals[k] * y_percent;
6118 }
6119 #endif
6120 }
6121 temp += pixelSizeInBytes;
6122 right = temp;
6123 percent = y_percent * highx_float;
6124 #if 0
6125 for (k = 0, temp_index = temp; k < components;
6126 k++, temp_index += element_size) {
6127 if (myswap_bytes) {
6128 totals[k] += __GLU_SWAP_2_BYTES(temp_index) * percent;
6129 } else {
6130 totals[k] += *(const GLushort*)temp_index * percent;
6131 }
6132 }
6133 #else
6134 (*extractPackedPixel)(isSwap,temp,extractTotals);
6135 for (k = 0; k < components; k++) {
6136 totals[k]+= extractTotals[k] * percent;
6137 }
6138 #endif
6139
6140 /* calculate the value for pixels in the last row */
6141
6142 y_percent = highy_float;
6143 percent = y_percent * (1-lowx_float);
6144 temp = (const char *)dataIn + xindex + highy_int * rowSizeInBytes;
6145 #if 0
6146 for (k = 0, temp_index = temp; k < components;
6147 k++, temp_index += element_size) {
6148 if (myswap_bytes) {
6149 totals[k] += __GLU_SWAP_2_BYTES(temp_index) * percent;
6150 } else {
6151 totals[k] += *(const GLushort*)temp_index * percent;
6152 }
6153 }
6154 #else
6155 (*extractPackedPixel)(isSwap,temp,extractTotals);
6156 for (k = 0; k < components; k++) {
6157 totals[k]+= extractTotals[k] * percent;
6158 }
6159 #endif
6160 for(l = lowx_int+1; l < highx_int; l++) {
6161 temp += pixelSizeInBytes;
6162 #if 0
6163 for (k = 0, temp_index = temp; k < components;
6164 k++, temp_index += element_size) {
6165 if (myswap_bytes) {
6166 totals[k] +=
6167 __GLU_SWAP_2_BYTES(temp_index) * y_percent;
6168 } else {
6169 totals[k] += *(const GLushort*)temp_index * y_percent;
6170 }
6171 }
6172 #else
6173 (*extractPackedPixel)(isSwap,temp,extractTotals);
6174 for (k = 0; k < components; k++) {
6175 totals[k]+= extractTotals[k] * y_percent;
6176 }
6177 #endif
6178
6179 }
6180 temp += pixelSizeInBytes;
6181 percent = y_percent * highx_float;
6182 #if 0
6183 for (k = 0, temp_index = temp; k < components;
6184 k++, temp_index += element_size) {
6185 if (myswap_bytes) {
6186 totals[k] += __GLU_SWAP_2_BYTES(temp_index) * percent;
6187 } else {
6188 totals[k] += *(const GLushort*)temp_index * percent;
6189 }
6190 }
6191 #else
6192 (*extractPackedPixel)(isSwap,temp,extractTotals);
6193 for (k = 0; k < components; k++) {
6194 totals[k]+= extractTotals[k] * percent;
6195 }
6196 #endif
6197
6198 /* calculate the value for pixels in the 1st and last column */
6199 for(m = lowy_int+1; m < highy_int; m++) {
6200 left += rowSizeInBytes;
6201 right += rowSizeInBytes;
6202 #if 0
6203 for (k = 0; k < components;
6204 k++, left += element_size, right += element_size) {
6205 if (myswap_bytes) {
6206 totals[k] +=
6207 __GLU_SWAP_2_BYTES(left) * (1-lowx_float) +
6208 __GLU_SWAP_2_BYTES(right) * highx_float;
6209 } else {
6210 totals[k] += *(const GLushort*)left * (1-lowx_float)
6211 + *(const GLushort*)right * highx_float;
6212 }
6213 }
6214 #else
6215 (*extractPackedPixel)(isSwap,left,extractTotals);
6216 (*extractPackedPixel)(isSwap,right,extractMoreTotals);
6217 for (k = 0; k < components; k++) {
6218 totals[k]+= (extractTotals[k]*(1-lowx_float) +
6219 extractMoreTotals[k]*highx_float);
6220 }
6221 #endif
6222 }
6223 } else if (highy_int > lowy_int) {
6224 x_percent = highx_float - lowx_float;
6225 percent = (1-lowy_float)*x_percent;
6226 temp = (const char *)dataIn + xindex + lowy_int*rowSizeInBytes;
6227 #if 0
6228 for (k = 0, temp_index = temp; k < components;
6229 k++, temp_index += element_size) {
6230 if (myswap_bytes) {
6231 totals[k] += __GLU_SWAP_2_BYTES(temp_index) * percent;
6232 } else {
6233 totals[k] += *(const GLushort*)temp_index * percent;
6234 }
6235 }
6236 #else
6237 (*extractPackedPixel)(isSwap,temp,extractTotals);
6238 for (k = 0; k < components; k++) {
6239 totals[k]+= extractTotals[k] * percent;
6240 }
6241 #endif
6242 for(m = lowy_int+1; m < highy_int; m++) {
6243 temp += rowSizeInBytes;
6244 #if 0
6245 for (k = 0, temp_index = temp; k < components;
6246 k++, temp_index += element_size) {
6247 if (myswap_bytes) {
6248 totals[k] +=
6249 __GLU_SWAP_2_BYTES(temp_index) * x_percent;
6250 } else {
6251 totals[k] += *(const GLushort*)temp_index * x_percent;
6252 }
6253 }
6254 #else
6255 (*extractPackedPixel)(isSwap,temp,extractTotals);
6256 for (k = 0; k < components; k++) {
6257 totals[k]+= extractTotals[k] * x_percent;
6258 }
6259 #endif
6260 }
6261 percent = x_percent * highy_float;
6262 temp += rowSizeInBytes;
6263 #if 0
6264 for (k = 0, temp_index = temp; k < components;
6265 k++, temp_index += element_size) {
6266 if (myswap_bytes) {
6267 totals[k] += __GLU_SWAP_2_BYTES(temp_index) * percent;
6268 } else {
6269 totals[k] += *(const GLushort*)temp_index * percent;
6270 }
6271 }
6272 #else
6273 (*extractPackedPixel)(isSwap,temp,extractTotals);
6274 for (k = 0; k < components; k++) {
6275 totals[k]+= extractTotals[k] * percent;
6276 }
6277 #endif
6278 } else if (highx_int > lowx_int) {
6279 y_percent = highy_float - lowy_float;
6280 percent = (1-lowx_float)*y_percent;
6281 temp = (const char *)dataIn + xindex + lowy_int*rowSizeInBytes;
6282 #if 0
6283 for (k = 0, temp_index = temp; k < components;
6284 k++, temp_index += element_size) {
6285 if (myswap_bytes) {
6286 totals[k] += __GLU_SWAP_2_BYTES(temp_index) * percent;
6287 } else {
6288 totals[k] += *(const GLushort*)temp_index * percent;
6289 }
6290 }
6291 #else
6292 (*extractPackedPixel)(isSwap,temp,extractTotals);
6293 for (k = 0; k < components; k++) {
6294 totals[k]+= extractTotals[k] * percent;
6295 }
6296 #endif
6297 for (l = lowx_int+1; l < highx_int; l++) {
6298 temp += pixelSizeInBytes;
6299 #if 0
6300 for (k = 0, temp_index = temp; k < components;
6301 k++, temp_index += element_size) {
6302 if (myswap_bytes) {
6303 totals[k] +=
6304 __GLU_SWAP_2_BYTES(temp_index) * y_percent;
6305 } else {
6306 totals[k] += *(const GLushort*)temp_index * y_percent;
6307 }
6308 }
6309 #else
6310 (*extractPackedPixel)(isSwap,temp,extractTotals);
6311 for (k = 0; k < components; k++) {
6312 totals[k]+= extractTotals[k] * y_percent;
6313 }
6314 #endif
6315 }
6316 temp += pixelSizeInBytes;
6317 percent = y_percent * highx_float;
6318 #if 0
6319 for (k = 0, temp_index = temp; k < components;
6320 k++, temp_index += element_size) {
6321 if (myswap_bytes) {
6322 totals[k] += __GLU_SWAP_2_BYTES(temp_index) * percent;
6323 } else {
6324 totals[k] += *(const GLushort*)temp_index * percent;
6325 }
6326 }
6327 #else
6328 (*extractPackedPixel)(isSwap,temp,extractTotals);
6329 for (k = 0; k < components; k++) {
6330 totals[k]+= extractTotals[k] * percent;
6331 }
6332 #endif
6333 } else {
6334 percent = (highy_float-lowy_float)*(highx_float-lowx_float);
6335 temp = (const char *)dataIn + xindex + lowy_int * rowSizeInBytes;
6336 #if 0
6337 for (k = 0, temp_index = temp; k < components;
6338 k++, temp_index += element_size) {
6339 if (myswap_bytes) {
6340 totals[k] += __GLU_SWAP_2_BYTES(temp_index) * percent;
6341 } else {
6342 totals[k] += *(const GLushort*)temp_index * percent;
6343 }
6344 }
6345 #else
6346 (*extractPackedPixel)(isSwap,temp,extractTotals);
6347 for (k = 0; k < components; k++) {
6348 totals[k]+= extractTotals[k] * percent;
6349 }
6350 #endif
6351 }
6352
6353 /* this is for the pixels in the body */
6354 temp0 = (const char *)dataIn + xindex + pixelSizeInBytes + (lowy_int+1)*rowSizeInBytes;
6355 for (m = lowy_int+1; m < highy_int; m++) {
6356 temp = temp0;
6357 for(l = lowx_int+1; l < highx_int; l++) {
6358 #if 0
6359 for (k = 0, temp_index = temp; k < components;
6360 k++, temp_index += element_size) {
6361 if (myswap_bytes) {
6362 totals[k] += __GLU_SWAP_2_BYTES(temp_index);
6363 } else {
6364 totals[k] += *(const GLushort*)temp_index;
6365 }
6366 }
6367 #else
6368 (*extractPackedPixel)(isSwap,temp,extractTotals);
6369 for (k = 0; k < components; k++) {
6370 totals[k]+= extractTotals[k];
6371 }
6372 #endif
6373 temp += pixelSizeInBytes;
6374 }
6375 temp0 += rowSizeInBytes;
6376 }
6377
6378 outindex = (j + (i * widthOut)); /* * (components == 1) */
6379 #if 0
6380 for (k = 0; k < components; k++) {
6381 dataout[outindex + k] = totals[k]/area;
6382 /*printf("totals[%d] = %f\n", k, totals[k]);*/
6383 }
6384 #else
6385 for (k = 0; k < components; k++) {
6386 shoveTotals[k]= totals[k]/area;
6387 }
6388 (*shovePackedPixel)(shoveTotals,outindex,(void *)dataOut);
6389 #endif
6390 lowx_int = highx_int;
6391 lowx_float = highx_float;
6392 highx_int += convx_int;
6393 highx_float += convx_float;
6394 if(highx_float > 1) {
6395 highx_float -= 1.0;
6396 highx_int++;
6397 }
6398 }
6399 lowy_int = highy_int;
6400 lowy_float = highy_float;
6401 highy_int += convy_int;
6402 highy_float += convy_float;
6403 if(highy_float > 1) {
6404 highy_float -= 1.0;
6405 highy_int++;
6406 }
6407 }
6408
6409 assert(outindex == (widthOut*heightOut - 1));
6410 } /* scaleInternalPackedPixel() */
6411
6412 /* rowSizeInBytes is at least the width (in bytes) due to padding on
6413 * inputs; not always equal. Output NEVER has row padding.
6414 */
6415 static void halveImagePackedPixel(int components,
6416 void (*extractPackedPixel)
6417 (int, const void *,GLfloat []),
6418 void (*shovePackedPixel)
6419 (const GLfloat [],int, void *),
6420 GLint width, GLint height,
6421 const void *dataIn, void *dataOut,
6422 GLint pixelSizeInBytes,
6423 GLint rowSizeInBytes, GLint isSwap)
6424 {
6425 /* handle case where there is only 1 column/row */
6426 if (width == 1 || height == 1) {
6427 assert(!(width == 1 && height == 1)); /* can't be 1x1 */
6428 halve1DimagePackedPixel(components,extractPackedPixel,shovePackedPixel,
6429 width,height,dataIn,dataOut,pixelSizeInBytes,
6430 rowSizeInBytes,isSwap);
6431 return;
6432 }
6433
6434 {
6435 int ii, jj;
6436
6437 int halfWidth= width / 2;
6438 int halfHeight= height / 2;
6439 const char *src= (const char *) dataIn;
6440 int padBytes= rowSizeInBytes - (width*pixelSizeInBytes);
6441 int outIndex= 0;
6442
6443 for (ii= 0; ii< halfHeight; ii++) {
6444 for (jj= 0; jj< halfWidth; jj++) {
6445 #define BOX4 4
6446 float totals[4]; /* 4 is maximum components */
6447 float extractTotals[BOX4][4]; /* 4 is maximum components */
6448 int cc;
6449
6450 (*extractPackedPixel)(isSwap,src,
6451 &extractTotals[0][0]);
6452 (*extractPackedPixel)(isSwap,(src+pixelSizeInBytes),
6453 &extractTotals[1][0]);
6454 (*extractPackedPixel)(isSwap,(src+rowSizeInBytes),
6455 &extractTotals[2][0]);
6456 (*extractPackedPixel)(isSwap,
6457 (src+rowSizeInBytes+pixelSizeInBytes),
6458 &extractTotals[3][0]);
6459 for (cc = 0; cc < components; cc++) {
6460 int kk;
6461
6462 /* grab 4 pixels to average */
6463 totals[cc]= 0.0;
6464 /* totals[RED]= extractTotals[0][RED]+extractTotals[1][RED]+
6465 * extractTotals[2][RED]+extractTotals[3][RED];
6466 * totals[RED]/= 4.0;
6467 */
6468 for (kk = 0; kk < BOX4; kk++) {
6469 totals[cc]+= extractTotals[kk][cc];
6470 }
6471 totals[cc]/= (float)BOX4;
6472 }
6473 (*shovePackedPixel)(totals,outIndex,dataOut);
6474
6475 outIndex++;
6476 /* skip over to next square of 4 */
6477 src+= pixelSizeInBytes + pixelSizeInBytes;
6478 }
6479 /* skip past pad bytes, if any, to get to next row */
6480 src+= padBytes;
6481
6482 /* src is at beginning of a row here, but it's the second row of
6483 * the square block of 4 pixels that we just worked on so we
6484 * need to go one more row.
6485 * i.e.,
6486 * OO...
6487 * here -->OO...
6488 * but want -->OO...
6489 * OO...
6490 * ...
6491 */
6492 src+= rowSizeInBytes;
6493 }
6494
6495 /* both pointers must reach one byte after the end */
6496 assert(src == &((const char *)dataIn)[rowSizeInBytes*height]);
6497 assert(outIndex == halfWidth * halfHeight);
6498 }
6499 } /* halveImagePackedPixel() */
6500
6501 static void halve1DimagePackedPixel(int components,
6502 void (*extractPackedPixel)
6503 (int, const void *,GLfloat []),
6504 void (*shovePackedPixel)
6505 (const GLfloat [],int, void *),
6506 GLint width, GLint height,
6507 const void *dataIn, void *dataOut,
6508 GLint pixelSizeInBytes,
6509 GLint rowSizeInBytes, GLint isSwap)
6510 {
6511 int halfWidth= width / 2;
6512 int halfHeight= height / 2;
6513 const char *src= (const char *) dataIn;
6514 int jj;
6515
6516 assert(width == 1 || height == 1); /* must be 1D */
6517 assert(width != height); /* can't be square */
6518
6519 if (height == 1) { /* 1 row */
6520 int outIndex= 0;
6521
6522 assert(width != 1); /* widthxheight can't be 1x1 */
6523 halfHeight= 1;
6524
6525 /* one horizontal row with possible pad bytes */
6526
6527 for (jj= 0; jj< halfWidth; jj++) {
6528 #define BOX2 2
6529 float totals[4]; /* 4 is maximum components */
6530 float extractTotals[BOX2][4]; /* 4 is maximum components */
6531 int cc;
6532
6533 /* average two at a time, instead of four */
6534 (*extractPackedPixel)(isSwap,src,
6535 &extractTotals[0][0]);
6536 (*extractPackedPixel)(isSwap,(src+pixelSizeInBytes),
6537 &extractTotals[1][0]);
6538 for (cc = 0; cc < components; cc++) {
6539 int kk;
6540
6541 /* grab 2 pixels to average */
6542 totals[cc]= 0.0;
6543 /* totals[RED]= extractTotals[0][RED]+extractTotals[1][RED];
6544 * totals[RED]/= 2.0;
6545 */
6546 for (kk = 0; kk < BOX2; kk++) {
6547 totals[cc]+= extractTotals[kk][cc];
6548 }
6549 totals[cc]/= (float)BOX2;
6550 }
6551 (*shovePackedPixel)(totals,outIndex,dataOut);
6552
6553 outIndex++;
6554 /* skip over to next group of 2 */
6555 src+= pixelSizeInBytes + pixelSizeInBytes;
6556 }
6557
6558 {
6559 int padBytes= rowSizeInBytes - (width*pixelSizeInBytes);
6560 src+= padBytes; /* for assertion only */
6561 }
6562 assert(src == &((const char *)dataIn)[rowSizeInBytes]);
6563 assert(outIndex == halfWidth * halfHeight);
6564 }
6565 else if (width == 1) { /* 1 column */
6566 int outIndex= 0;
6567
6568 assert(height != 1); /* widthxheight can't be 1x1 */
6569 halfWidth= 1;
6570 /* one vertical column with possible pad bytes per row */
6571 /* average two at a time */
6572
6573 for (jj= 0; jj< halfHeight; jj++) {
6574 #define BOX2 2
6575 float totals[4]; /* 4 is maximum components */
6576 float extractTotals[BOX2][4]; /* 4 is maximum components */
6577 int cc;
6578
6579 /* average two at a time, instead of four */
6580 (*extractPackedPixel)(isSwap,src,
6581 &extractTotals[0][0]);
6582 (*extractPackedPixel)(isSwap,(src+rowSizeInBytes),
6583 &extractTotals[1][0]);
6584 for (cc = 0; cc < components; cc++) {
6585 int kk;
6586
6587 /* grab 2 pixels to average */
6588 totals[cc]= 0.0;
6589 /* totals[RED]= extractTotals[0][RED]+extractTotals[1][RED];
6590 * totals[RED]/= 2.0;
6591 */
6592 for (kk = 0; kk < BOX2; kk++) {
6593 totals[cc]+= extractTotals[kk][cc];
6594 }
6595 totals[cc]/= (float)BOX2;
6596 }
6597 (*shovePackedPixel)(totals,outIndex,dataOut);
6598
6599 outIndex++;
6600 src+= rowSizeInBytes + rowSizeInBytes; /* go to row after next */
6601 }
6602
6603 assert(src == &((const char *)dataIn)[rowSizeInBytes*height]);
6604 assert(outIndex == halfWidth * halfHeight);
6605 }
6606 } /* halve1DimagePackedPixel() */
6607
6608 /*===========================================================================*/
6609
6610 #ifdef RESOLVE_3D_TEXTURE_SUPPORT
6611 /*
6612 * This section ensures that GLU 1.3 will load and run on
6613 * a GL 1.1 implementation. It dynamically resolves the
6614 * call to glTexImage3D() which might not be available.
6615 * Or is it might be supported as an extension.
6616 * Contributed by Gerk Huisma <gerk@five-d.demon.nl>.
6617 */
6618
6619 typedef void (GLAPIENTRY *TexImage3Dproc)( GLenum target, GLint level,
6620 GLenum internalFormat,
6621 GLsizei width, GLsizei height,
6622 GLsizei depth, GLint border,
6623 GLenum format, GLenum type,
6624 const GLvoid *pixels );
6625
6626 static TexImage3Dproc pTexImage3D = 0;
6627
6628 #if !defined(_WIN32) && !defined(__WIN32__)
6629 # include <dlfcn.h>
6630 # include <sys/types.h>
6631 #else
6632 WINGDIAPI PROC WINAPI wglGetProcAddress(LPCSTR);
6633 #endif
6634
6635 static void gluTexImage3D( GLenum target, GLint level,
6636 GLenum internalFormat,
6637 GLsizei width, GLsizei height,
6638 GLsizei depth, GLint border,
6639 GLenum format, GLenum type,
6640 const GLvoid *pixels )
6641 {
6642 if (!pTexImage3D) {
6643 #if defined(_WIN32) || defined(__WIN32__)
6644 pTexImage3D = (TexImage3Dproc) wglGetProcAddress("glTexImage3D");
6645 if (!pTexImage3D)
6646 pTexImage3D = (TexImage3Dproc) wglGetProcAddress("glTexImage3DEXT");
6647 #else
6648 void *libHandle = dlopen("libgl.so", RTLD_LAZY);
6649 pTexImage3D = TexImage3Dproc) dlsym(libHandle, "glTexImage3D" );
6650 if (!pTexImage3D)
6651 pTexImage3D = (TexImage3Dproc) dlsym(libHandle,"glTexImage3DEXT");
6652 dlclose(libHandle);
6653 #endif
6654 }
6655
6656 /* Now call glTexImage3D */
6657 if (pTexImage3D)
6658 pTexImage3D(target, level, internalFormat, width, height,
6659 depth, border, format, type, pixels);
6660 }
6661
6662 #else
6663
6664 /* Only bind to a GL 1.2 implementation: */
6665 #define gluTexImage3D glTexImage3D
6666
6667 #endif
6668
6669 static GLint imageSize3D(GLint width, GLint height, GLint depth,
6670 GLenum format, GLenum type)
6671 {
6672 int components= elements_per_group(format,type);
6673 int bytes_per_row= bytes_per_element(type) * width;
6674
6675 assert(width > 0 && height > 0 && depth > 0);
6676 assert(type != GL_BITMAP);
6677
6678 return bytes_per_row * height * depth * components;
6679 } /* imageSize3D() */
6680
6681 static void fillImage3D(const PixelStorageModes *psm,
6682 GLint width, GLint height, GLint depth, GLenum format,
6683 GLenum type, GLboolean indexFormat,
6684 const void *userImage, GLushort *newImage)
6685 {
6686 int myswapBytes;
6687 int components;
6688 int groupsPerLine;
6689 int elementSize;
6690 int groupSize;
6691 int rowSize;
6692 int padding;
6693 int elementsPerLine;
6694 int rowsPerImage;
6695 int imageSize;
6696 const GLubyte *start, *rowStart, *iter;
6697 GLushort *iter2;
6698 int ww, hh, dd, k;
6699
6700 myswapBytes= psm->unpack_swap_bytes;
6701 components= elements_per_group(format,type);
6702 if (psm->unpack_row_length > 0) {
6703 groupsPerLine= psm->unpack_row_length;
6704 }
6705 else {
6706 groupsPerLine= width;
6707 }
6708 elementSize= bytes_per_element(type);
6709 groupSize= elementSize * components;
6710 if (elementSize == 1) myswapBytes= 0;
6711
6712 /* 3dstuff begin */
6713 if (psm->unpack_image_height > 0) {
6714 rowsPerImage= psm->unpack_image_height;
6715 }
6716 else {
6717 rowsPerImage= height;
6718 }
6719 /* 3dstuff end */
6720
6721 rowSize= groupsPerLine * groupSize;
6722 padding= rowSize % psm->unpack_alignment;
6723 if (padding) {
6724 rowSize+= psm->unpack_alignment - padding;
6725 }
6726
6727 imageSize= rowsPerImage * rowSize; /* 3dstuff */
6728
6729 start= (const GLubyte *)userImage + psm->unpack_skip_rows * rowSize +
6730 psm->unpack_skip_pixels * groupSize +
6731 /*3dstuff*/
6732 psm->unpack_skip_images * imageSize;
6733 elementsPerLine = width * components;
6734
6735 iter2= newImage;
6736 for (dd= 0; dd < depth; dd++) {
6737 rowStart= start;
6738
6739 for (hh= 0; hh < height; hh++) {
6740 iter= rowStart;
6741
6742 for (ww= 0; ww < elementsPerLine; ww++) {
6743 Type_Widget widget;
6744 float extractComponents[4];
6745
6746 switch(type) {
6747 case GL_UNSIGNED_BYTE:
6748 if (indexFormat) {
6749 *iter2++ = *iter;
6750 } else {
6751 *iter2++ = (*iter) * 257;
6752 }
6753 break;
6754 case GL_BYTE:
6755 if (indexFormat) {
6756 *iter2++ = *((const GLbyte *) iter);
6757 } else {
6758 /* rough approx */
6759 *iter2++ = (*((const GLbyte *) iter)) * 516;
6760 }
6761 break;
6762 case GL_UNSIGNED_BYTE_3_3_2:
6763 extract332(0,iter,extractComponents);
6764 for (k = 0; k < 3; k++) {
6765 *iter2++ = (GLushort)(extractComponents[k]*65535);
6766 }
6767 break;
6768 case GL_UNSIGNED_BYTE_2_3_3_REV:
6769 extract233rev(0,iter,extractComponents);
6770 for (k = 0; k < 3; k++) {
6771 *iter2++ = (GLushort)(extractComponents[k]*65535);
6772 }
6773 break;
6774 case GL_UNSIGNED_SHORT_5_6_5:
6775 extract565(myswapBytes,iter,extractComponents);
6776 for (k = 0; k < 3; k++) {
6777 *iter2++ = (GLushort)(extractComponents[k]*65535);
6778 }
6779 break;
6780 case GL_UNSIGNED_SHORT_5_6_5_REV:
6781 extract565rev(myswapBytes,iter,extractComponents);
6782 for (k = 0; k < 3; k++) {
6783 *iter2++ = (GLushort)(extractComponents[k]*65535);
6784 }
6785 break;
6786 case GL_UNSIGNED_SHORT_4_4_4_4:
6787 extract4444(myswapBytes,iter,extractComponents);
6788 for (k = 0; k < 4; k++) {
6789 *iter2++ = (GLushort)(extractComponents[k]*65535);
6790 }
6791 break;
6792 case GL_UNSIGNED_SHORT_4_4_4_4_REV:
6793 extract4444rev(myswapBytes,iter,extractComponents);
6794 for (k = 0; k < 4; k++) {
6795 *iter2++ = (GLushort)(extractComponents[k]*65535);
6796 }
6797 break;
6798 case GL_UNSIGNED_SHORT_5_5_5_1:
6799 extract5551(myswapBytes,iter,extractComponents);
6800 for (k = 0; k < 4; k++) {
6801 *iter2++ = (GLushort)(extractComponents[k]*65535);
6802 }
6803 break;
6804 case GL_UNSIGNED_SHORT_1_5_5_5_REV:
6805 extract1555rev(myswapBytes,iter,extractComponents);
6806 for (k = 0; k < 4; k++) {
6807 *iter2++ = (GLushort)(extractComponents[k]*65535);
6808 }
6809 break;
6810 case GL_UNSIGNED_SHORT:
6811 case GL_SHORT:
6812 if (myswapBytes) {
6813 widget.ub[0] = iter[1];
6814 widget.ub[1] = iter[0];
6815 } else {
6816 widget.ub[0] = iter[0];
6817 widget.ub[1] = iter[1];
6818 }
6819 if (type == GL_SHORT) {
6820 if (indexFormat) {
6821 *iter2++ = widget.s[0];
6822 } else {
6823 /* rough approx */
6824 *iter2++ = widget.s[0]*2;
6825 }
6826 } else {
6827 *iter2++ = widget.us[0];
6828 }
6829 break;
6830 case GL_UNSIGNED_INT_8_8_8_8:
6831 extract8888(myswapBytes,iter,extractComponents);
6832 for (k = 0; k < 4; k++) {
6833 *iter2++ = (GLushort)(extractComponents[k]*65535);
6834 }
6835 break;
6836 case GL_UNSIGNED_INT_8_8_8_8_REV:
6837 extract8888rev(myswapBytes,iter,extractComponents);
6838 for (k = 0; k < 4; k++) {
6839 *iter2++ = (GLushort)(extractComponents[k]*65535);
6840 }
6841 break;
6842 case GL_UNSIGNED_INT_10_10_10_2:
6843 extract1010102(myswapBytes,iter,extractComponents);
6844 for (k = 0; k < 4; k++) {
6845 *iter2++ = (GLushort)(extractComponents[k]*65535);
6846 }
6847 break;
6848 case GL_UNSIGNED_INT_2_10_10_10_REV:
6849 extract2101010rev(myswapBytes,iter,extractComponents);
6850 for (k = 0; k < 4; k++) {
6851 *iter2++ = (GLushort)(extractComponents[k]*65535);
6852 }
6853 break;
6854 case GL_INT:
6855 case GL_UNSIGNED_INT:
6856 case GL_FLOAT:
6857 if (myswapBytes) {
6858 widget.ub[0] = iter[3];
6859 widget.ub[1] = iter[2];
6860 widget.ub[2] = iter[1];
6861 widget.ub[3] = iter[0];
6862 } else {
6863 widget.ub[0] = iter[0];
6864 widget.ub[1] = iter[1];
6865 widget.ub[2] = iter[2];
6866 widget.ub[3] = iter[3];
6867 }
6868 if (type == GL_FLOAT) {
6869 if (indexFormat) {
6870 *iter2++ = widget.f;
6871 } else {
6872 *iter2++ = 65535 * widget.f;
6873 }
6874 } else if (type == GL_UNSIGNED_INT) {
6875 if (indexFormat) {
6876 *iter2++ = widget.ui;
6877 } else {
6878 *iter2++ = widget.ui >> 16;
6879 }
6880 } else {
6881 if (indexFormat) {
6882 *iter2++ = widget.i;
6883 } else {
6884 *iter2++ = widget.i >> 15;
6885 }
6886 }
6887 break;
6888 default:
6889 assert(0);
6890 }
6891
6892 iter+= elementSize;
6893 } /* for ww */
6894 rowStart+= rowSize;
6895
6896 iter= rowStart; /* for assertion purposes */
6897 } /* for hh */
6898
6899 start+= imageSize;
6900 } /* for dd */
6901
6902 /* iterators should be one byte past end */
6903 if (!isTypePackedPixel(type)) {
6904 assert(iter2 == &newImage[width*height*depth*components]);
6905 }
6906 else {
6907 assert(iter2 == &newImage[width*height*depth*
6908 elements_per_group(format,0)]);
6909 }
6910 assert( iter == &((const GLubyte *)userImage)[rowSize*height*depth +
6911 psm->unpack_skip_rows * rowSize +
6912 psm->unpack_skip_pixels * groupSize +
6913 /*3dstuff*/
6914 psm->unpack_skip_images * imageSize] );
6915 } /* fillImage3D () */
6916
6917 static void scaleInternal3D(GLint components,
6918 GLint widthIn, GLint heightIn, GLint depthIn,
6919 const GLushort *dataIn,
6920 GLint widthOut, GLint heightOut, GLint depthOut,
6921 GLushort *dataOut)
6922 {
6923 float x, lowx, highx, convx, halfconvx;
6924 float y, lowy, highy, convy, halfconvy;
6925 float z, lowz, highz, convz, halfconvz;
6926 float xpercent,ypercent,zpercent;
6927 float percent;
6928 /* Max components in a format is 4, so... */
6929 float totals[4];
6930 float volume;
6931 int i,j,d,k,zint,yint,xint,xindex,yindex,zindex;
6932 int temp;
6933
6934 convz = (float) depthIn/depthOut;
6935 convy = (float) heightIn/heightOut;
6936 convx = (float) widthIn/widthOut;
6937 halfconvx = convx/2;
6938 halfconvy = convy/2;
6939 halfconvz = convz/2;
6940 for (d = 0; d < depthOut; d++) {
6941 z = convz * (d+0.5);
6942 if (depthIn > depthOut) {
6943 highz = z + halfconvz;
6944 lowz = z - halfconvz;
6945 } else {
6946 highz = z + 0.5;
6947 lowz = z - 0.5;
6948 }
6949 for (i = 0; i < heightOut; i++) {
6950 y = convy * (i+0.5);
6951 if (heightIn > heightOut) {
6952 highy = y + halfconvy;
6953 lowy = y - halfconvy;
6954 } else {
6955 highy = y + 0.5;
6956 lowy = y - 0.5;
6957 }
6958 for (j = 0; j < widthOut; j++) {
6959 x = convx * (j+0.5);
6960 if (widthIn > widthOut) {
6961 highx = x + halfconvx;
6962 lowx = x - halfconvx;
6963 } else {
6964 highx = x + 0.5;
6965 lowx = x - 0.5;
6966 }
6967
6968 /*
6969 ** Ok, now apply box filter to box that goes from (lowx, lowy,
6970 ** lowz) to (highx, highy, highz) on input data into this pixel
6971 ** on output data.
6972 */
6973 totals[0] = totals[1] = totals[2] = totals[3] = 0.0;
6974 volume = 0.0;
6975
6976 z = lowz;
6977 zint = floor(z);
6978 while (z < highz) {
6979 zindex = (zint + depthIn) % depthIn;
6980 if (highz < zint+1) {
6981 zpercent = highz - z;
6982 } else {
6983 zpercent = zint+1 - z;
6984 }
6985
6986 y = lowy;
6987 yint = floor(y);
6988 while (y < highy) {
6989 yindex = (yint + heightIn) % heightIn;
6990 if (highy < yint+1) {
6991 ypercent = highy - y;
6992 } else {
6993 ypercent = yint+1 - y;
6994 }
6995
6996 x = lowx;
6997 xint = floor(x);
6998
6999 while (x < highx) {
7000 xindex = (xint + widthIn) % widthIn;
7001 if (highx < xint+1) {
7002 xpercent = highx - x;
7003 } else {
7004 xpercent = xint+1 - x;
7005 }
7006
7007 percent = xpercent * ypercent * zpercent;
7008 volume += percent;
7009
7010 temp = (xindex + (yindex*widthIn) +
7011 (zindex*widthIn*heightIn)) * components;
7012 for (k = 0; k < components; k++) {
7013 assert(0 <= (temp+k) &&
7014 (temp+k) <
7015 (widthIn*heightIn*depthIn*components));
7016 totals[k] += dataIn[temp + k] * percent;
7017 }
7018
7019 xint++;
7020 x = xint;
7021 } /* while x */
7022
7023 yint++;
7024 y = yint;
7025 } /* while y */
7026
7027 zint++;
7028 z = zint;
7029 } /* while z */
7030
7031 temp = (j + (i * widthOut) +
7032 (d*widthOut*heightOut)) * components;
7033 for (k = 0; k < components; k++) {
7034 /* totals[] should be rounded in the case of enlarging an
7035 * RGB ramp when the type is 332 or 4444
7036 */
7037 assert(0 <= (temp+k) &&
7038 (temp+k) < (widthOut*heightOut*depthOut*components));
7039 dataOut[temp + k] = (totals[k]+0.5)/volume;
7040 }
7041 } /* for j */
7042 } /* for i */
7043 } /* for d */
7044 } /* scaleInternal3D() */
7045
7046 static void emptyImage3D(const PixelStorageModes *psm,
7047 GLint width, GLint height, GLint depth,
7048 GLenum format, GLenum type, GLboolean indexFormat,
7049 const GLushort *oldImage, void *userImage)
7050 {
7051 int myswapBytes;
7052 int components;
7053 int groupsPerLine;
7054 int elementSize;
7055 int groupSize;
7056 int rowSize;
7057 int padding;
7058 GLubyte *start, *rowStart, *iter;
7059 int elementsPerLine;
7060 const GLushort *iter2;
7061 int ii, jj, dd, k;
7062 int rowsPerImage;
7063 int imageSize;
7064
7065 myswapBytes= psm->pack_swap_bytes;
7066 components = elements_per_group(format,type);
7067 if (psm->pack_row_length > 0) {
7068 groupsPerLine = psm->pack_row_length;
7069 }
7070 else {
7071 groupsPerLine = width;
7072 }
7073
7074 elementSize= bytes_per_element(type);
7075 groupSize= elementSize * components;
7076 if (elementSize == 1) myswapBytes= 0;
7077
7078 /* 3dstuff begin */
7079 if (psm->pack_image_height > 0) {
7080 rowsPerImage= psm->pack_image_height;
7081 }
7082 else {
7083 rowsPerImage= height;
7084 }
7085
7086 /* 3dstuff end */
7087
7088 rowSize = groupsPerLine * groupSize;
7089 padding = rowSize % psm->pack_alignment;
7090 if (padding) {
7091 rowSize+= psm->pack_alignment - padding;
7092 }
7093
7094 imageSize= rowsPerImage * rowSize; /* 3dstuff */
7095
7096 start = (GLubyte *)userImage + psm->pack_skip_rows * rowSize +
7097 psm->pack_skip_pixels * groupSize +
7098 /*3dstuff*/
7099 psm->pack_skip_images * imageSize;
7100 elementsPerLine= width * components;
7101
7102 iter2 = oldImage;
7103 for (dd= 0; dd < depth; dd++) {
7104 rowStart= start;
7105
7106 for (ii= 0; ii< height; ii++) {
7107 iter = rowStart;
7108
7109 for (jj = 0; jj < elementsPerLine; jj++) {
7110 Type_Widget widget;
7111 float shoveComponents[4];
7112
7113 switch(type){
7114 case GL_UNSIGNED_BYTE:
7115 if (indexFormat) {
7116 *iter = *iter2++;
7117 } else {
7118 *iter = *iter2++ >> 8;
7119 }
7120 break;
7121 case GL_BYTE:
7122 if (indexFormat) {
7123 *((GLbyte *) iter) = *iter2++;
7124 } else {
7125 *((GLbyte *) iter) = *iter2++ >> 9;
7126 }
7127 break;
7128 case GL_UNSIGNED_BYTE_3_3_2:
7129 for (k = 0; k < 3; k++) {
7130 shoveComponents[k]= *iter2++ / 65535.0;
7131 }
7132 shove332(shoveComponents,0,(void *)iter);
7133 break;
7134 case GL_UNSIGNED_BYTE_2_3_3_REV:
7135 for (k = 0; k < 3; k++) {
7136 shoveComponents[k]= *iter2++ / 65535.0;
7137 }
7138 shove233rev(shoveComponents,0,(void *)iter);
7139 break;
7140 case GL_UNSIGNED_SHORT_5_6_5:
7141 for (k = 0; k < 3; k++) {
7142 shoveComponents[k]= *iter2++ / 65535.0;
7143 }
7144 shove565(shoveComponents,0,(void *)&widget.us[0]);
7145 if (myswapBytes) {
7146 iter[0] = widget.ub[1];
7147 iter[1] = widget.ub[0];
7148 }
7149 else {
7150 *(GLushort *)iter = widget.us[0];
7151 }
7152 break;
7153 case GL_UNSIGNED_SHORT_5_6_5_REV:
7154 for (k = 0; k < 3; k++) {
7155 shoveComponents[k]= *iter2++ / 65535.0;
7156 }
7157 shove565rev(shoveComponents,0,(void *)&widget.us[0]);
7158 if (myswapBytes) {
7159 iter[0] = widget.ub[1];
7160 iter[1] = widget.ub[0];
7161 }
7162 else {
7163 *(GLushort *)iter = widget.us[0];
7164 }
7165 break;
7166 case GL_UNSIGNED_SHORT_4_4_4_4:
7167 for (k = 0; k < 4; k++) {
7168 shoveComponents[k]= *iter2++ / 65535.0;
7169 }
7170 shove4444(shoveComponents,0,(void *)&widget.us[0]);
7171 if (myswapBytes) {
7172 iter[0] = widget.ub[1];
7173 iter[1] = widget.ub[0];
7174 } else {
7175 *(GLushort *)iter = widget.us[0];
7176 }
7177 break;
7178 case GL_UNSIGNED_SHORT_4_4_4_4_REV:
7179 for (k = 0; k < 4; k++) {
7180 shoveComponents[k]= *iter2++ / 65535.0;
7181 }
7182 shove4444rev(shoveComponents,0,(void *)&widget.us[0]);
7183 if (myswapBytes) {
7184 iter[0] = widget.ub[1];
7185 iter[1] = widget.ub[0];
7186 } else {
7187 *(GLushort *)iter = widget.us[0];
7188 }
7189 break;
7190 case GL_UNSIGNED_SHORT_5_5_5_1:
7191 for (k = 0; k < 4; k++) {
7192 shoveComponents[k]= *iter2++ / 65535.0;
7193 }
7194 shove5551(shoveComponents,0,(void *)&widget.us[0]);
7195 if (myswapBytes) {
7196 iter[0] = widget.ub[1];
7197 iter[1] = widget.ub[0];
7198 } else {
7199 *(GLushort *)iter = widget.us[0];
7200 }
7201 break;
7202 case GL_UNSIGNED_SHORT_1_5_5_5_REV:
7203 for (k = 0; k < 4; k++) {
7204 shoveComponents[k]= *iter2++ / 65535.0;
7205 }
7206 shove1555rev(shoveComponents,0,(void *)&widget.us[0]);
7207 if (myswapBytes) {
7208 iter[0] = widget.ub[1];
7209 iter[1] = widget.ub[0];
7210 } else {
7211 *(GLushort *)iter = widget.us[0];
7212 }
7213 break;
7214 case GL_UNSIGNED_SHORT:
7215 case GL_SHORT:
7216 if (type == GL_SHORT) {
7217 if (indexFormat) {
7218 widget.s[0] = *iter2++;
7219 } else {
7220 widget.s[0] = *iter2++ >> 1;
7221 }
7222 } else {
7223 widget.us[0] = *iter2++;
7224 }
7225 if (myswapBytes) {
7226 iter[0] = widget.ub[1];
7227 iter[1] = widget.ub[0];
7228 } else {
7229 iter[0] = widget.ub[0];
7230 iter[1] = widget.ub[1];
7231 }
7232 break;
7233 case GL_UNSIGNED_INT_8_8_8_8:
7234 for (k = 0; k < 4; k++) {
7235 shoveComponents[k]= *iter2++ / 65535.0;
7236 }
7237 shove8888(shoveComponents,0,(void *)&widget.ui);
7238 if (myswapBytes) {
7239 iter[3] = widget.ub[0];
7240 iter[2] = widget.ub[1];
7241 iter[1] = widget.ub[2];
7242 iter[0] = widget.ub[3];
7243 } else {
7244 *(GLuint *)iter= widget.ui;
7245 }
7246 break;
7247 case GL_UNSIGNED_INT_8_8_8_8_REV:
7248 for (k = 0; k < 4; k++) {
7249 shoveComponents[k]= *iter2++ / 65535.0;
7250 }
7251 shove8888rev(shoveComponents,0,(void *)&widget.ui);
7252 if (myswapBytes) {
7253 iter[3] = widget.ub[0];
7254 iter[2] = widget.ub[1];
7255 iter[1] = widget.ub[2];
7256 iter[0] = widget.ub[3];
7257 } else {
7258 *(GLuint *)iter= widget.ui;
7259 }
7260 break;
7261 case GL_UNSIGNED_INT_10_10_10_2:
7262 for (k = 0; k < 4; k++) {
7263 shoveComponents[k]= *iter2++ / 65535.0;
7264 }
7265 shove1010102(shoveComponents,0,(void *)&widget.ui);
7266 if (myswapBytes) {
7267 iter[3] = widget.ub[0];
7268 iter[2] = widget.ub[1];
7269 iter[1] = widget.ub[2];
7270 iter[0] = widget.ub[3];
7271 } else {
7272 *(GLuint *)iter= widget.ui;
7273 }
7274 break;
7275 case GL_UNSIGNED_INT_2_10_10_10_REV:
7276 for (k = 0; k < 4; k++) {
7277 shoveComponents[k]= *iter2++ / 65535.0;
7278 }
7279 shove2101010rev(shoveComponents,0,(void *)&widget.ui);
7280 if (myswapBytes) {
7281 iter[3] = widget.ub[0];
7282 iter[2] = widget.ub[1];
7283 iter[1] = widget.ub[2];
7284 iter[0] = widget.ub[3];
7285 } else {
7286 *(GLuint *)iter= widget.ui;
7287 }
7288 break;
7289 case GL_INT:
7290 case GL_UNSIGNED_INT:
7291 case GL_FLOAT:
7292 if (type == GL_FLOAT) {
7293 if (indexFormat) {
7294 widget.f = *iter2++;
7295 } else {
7296 widget.f = *iter2++ / (float) 65535.0;
7297 }
7298 } else if (type == GL_UNSIGNED_INT) {
7299 if (indexFormat) {
7300 widget.ui = *iter2++;
7301 } else {
7302 widget.ui = (unsigned int) *iter2++ * 65537;
7303 }
7304 } else {
7305 if (indexFormat) {
7306 widget.i = *iter2++;
7307 } else {
7308 widget.i = ((unsigned int) *iter2++ * 65537)/2;
7309 }
7310 }
7311 if (myswapBytes) {
7312 iter[3] = widget.ub[0];
7313 iter[2] = widget.ub[1];
7314 iter[1] = widget.ub[2];
7315 iter[0] = widget.ub[3];
7316 } else {
7317 iter[0] = widget.ub[0];
7318 iter[1] = widget.ub[1];
7319 iter[2] = widget.ub[2];
7320 iter[3] = widget.ub[3];
7321 }
7322 break;
7323 default:
7324 assert(0);
7325 }
7326
7327 iter+= elementSize;
7328 } /* for jj */
7329
7330 rowStart+= rowSize;
7331 } /* for ii */
7332
7333 start+= imageSize;
7334 } /* for dd */
7335
7336 /* iterators should be one byte past end */
7337 if (!isTypePackedPixel(type)) {
7338 assert(iter2 == &oldImage[width*height*depth*components]);
7339 }
7340 else {
7341 assert(iter2 == &oldImage[width*height*depth*
7342 elements_per_group(format,0)]);
7343 }
7344 assert( iter == &((GLubyte *)userImage)[rowSize*height*depth +
7345 psm->unpack_skip_rows * rowSize +
7346 psm->unpack_skip_pixels * groupSize +
7347 /*3dstuff*/
7348 psm->unpack_skip_images * imageSize] );
7349 } /* emptyImage3D() */
7350
7351 static
7352 int gluScaleImage3D(GLenum format,
7353 GLint widthIn, GLint heightIn, GLint depthIn,
7354 GLenum typeIn, const void *dataIn,
7355 GLint widthOut, GLint heightOut, GLint depthOut,
7356 GLenum typeOut, void *dataOut)
7357 {
7358 int components;
7359 GLushort *beforeImage, *afterImage;
7360 PixelStorageModes psm;
7361
7362 if (widthIn == 0 || heightIn == 0 || depthIn == 0 ||
7363 widthOut == 0 || heightOut == 0 || depthOut == 0) {
7364 return 0;
7365 }
7366
7367 if (widthIn < 0 || heightIn < 0 || depthIn < 0 ||
7368 widthOut < 0 || heightOut < 0 || depthOut < 0) {
7369 return GLU_INVALID_VALUE;
7370 }
7371
7372 if (!legalFormat(format) || !legalType(typeIn) || !legalType(typeOut) ||
7373 typeIn == GL_BITMAP || typeOut == GL_BITMAP) {
7374 return GLU_INVALID_ENUM;
7375 }
7376 if (!isLegalFormatForPackedPixelType(format, typeIn)) {
7377 return GLU_INVALID_OPERATION;
7378 }
7379 if (!isLegalFormatForPackedPixelType(format, typeOut)) {
7380 return GLU_INVALID_OPERATION;
7381 }
7382
7383 beforeImage = malloc(imageSize3D(widthIn, heightIn, depthIn, format,
7384 GL_UNSIGNED_SHORT));
7385 afterImage = malloc(imageSize3D(widthOut, heightOut, depthOut, format,
7386 GL_UNSIGNED_SHORT));
7387 if (beforeImage == NULL || afterImage == NULL) {
7388 free(beforeImage);
7389 free(afterImage);
7390 return GLU_OUT_OF_MEMORY;
7391 }
7392 retrieveStoreModes3D(&psm);
7393
7394 fillImage3D(&psm,widthIn,heightIn,depthIn,format,typeIn, is_index(format),
7395 dataIn, beforeImage);
7396 components = elements_per_group(format,0);
7397 scaleInternal3D(components,widthIn,heightIn,depthIn,beforeImage,
7398 widthOut,heightOut,depthOut,afterImage);
7399 emptyImage3D(&psm,widthOut,heightOut,depthOut,format,typeOut,
7400 is_index(format),afterImage, dataOut);
7401 free((void *) beforeImage);
7402 free((void *) afterImage);
7403
7404 return 0;
7405 } /* gluScaleImage3D() */
7406
7407
7408 static void closestFit3D(GLenum target, GLint width, GLint height, GLint depth,
7409 GLint internalFormat, GLenum format, GLenum type,
7410 GLint *newWidth, GLint *newHeight, GLint *newDepth)
7411 {
7412 GLint widthPowerOf2= nearestPower(width);
7413 GLint heightPowerOf2= nearestPower(height);
7414 GLint depthPowerOf2= nearestPower(depth);
7415 GLint proxyWidth;
7416
7417 do {
7418 /* compute level 1 width & height & depth, clamping each at 1 */
7419 GLint widthAtLevelOne= (widthPowerOf2 > 1) ?
7420 widthPowerOf2 >> 1 :
7421 widthPowerOf2;
7422 GLint heightAtLevelOne= (heightPowerOf2 > 1) ?
7423 heightPowerOf2 >> 1 :
7424 heightPowerOf2;
7425 GLint depthAtLevelOne= (depthPowerOf2 > 1) ?
7426 depthPowerOf2 >> 1 :
7427 depthPowerOf2;
7428 GLenum proxyTarget = GL_PROXY_TEXTURE_3D;
7429 assert(widthAtLevelOne > 0);
7430 assert(heightAtLevelOne > 0);
7431 assert(depthAtLevelOne > 0);
7432
7433 /* does width x height x depth at level 1 & all their mipmaps fit? */
7434 assert(target == GL_TEXTURE_3D || target == GL_PROXY_TEXTURE_3D);
7435 gluTexImage3D(proxyTarget, 1, /* must be non-zero */
7436 internalFormat,
7437 widthAtLevelOne,heightAtLevelOne,depthAtLevelOne,
7438 0,format,type,NULL);
7439 glGetTexLevelParameteriv(proxyTarget, 1,GL_TEXTURE_WIDTH,&proxyWidth);
7440 /* does it fit??? */
7441 if (proxyWidth == 0) { /* nope, so try again with these sizes */
7442 if (widthPowerOf2 == 1 && heightPowerOf2 == 1 &&
7443 depthPowerOf2 == 1) {
7444 *newWidth= *newHeight= *newDepth= 1; /* must fit 1x1x1 texture */
7445 return;
7446 }
7447 widthPowerOf2= widthAtLevelOne;
7448 heightPowerOf2= heightAtLevelOne;
7449 depthPowerOf2= depthAtLevelOne;
7450 }
7451 /* else it does fit */
7452 } while (proxyWidth == 0);
7453 /* loop must terminate! */
7454
7455 /* return the width & height at level 0 that fits */
7456 *newWidth= widthPowerOf2;
7457 *newHeight= heightPowerOf2;
7458 *newDepth= depthPowerOf2;
7459 /*printf("Proxy Textures\n");*/
7460 } /* closestFit3D() */
7461
7462 static void halveImagePackedPixelSlice(int components,
7463 void (*extractPackedPixel)
7464 (int, const void *,GLfloat []),
7465 void (*shovePackedPixel)
7466 (const GLfloat [],int, void *),
7467 GLint width, GLint height, GLint depth,
7468 const void *dataIn, void *dataOut,
7469 GLint pixelSizeInBytes,
7470 GLint rowSizeInBytes,
7471 GLint imageSizeInBytes,
7472 GLint isSwap)
7473 {
7474 int ii, jj;
7475 int halfWidth= width / 2;
7476 int halfHeight= height / 2;
7477 int halfDepth= depth / 2;
7478 const char *src= (const char *)dataIn;
7479 int outIndex= 0;
7480
7481 assert((width == 1 || height == 1) && depth >= 2);
7482
7483 if (width == height) { /* a 1-pixel column viewed from top */
7484 assert(width == 1 && height == 1);
7485 assert(depth >= 2);
7486
7487 for (ii= 0; ii< halfDepth; ii++) {
7488 float totals[4];
7489 float extractTotals[BOX2][4];
7490 int cc;
7491
7492 (*extractPackedPixel)(isSwap,src,&extractTotals[0][0]);
7493 (*extractPackedPixel)(isSwap,(src+imageSizeInBytes),
7494 &extractTotals[1][0]);
7495 for (cc = 0; cc < components; cc++) {
7496 int kk;
7497
7498 /* average 2 pixels since only a column */
7499 totals[cc]= 0.0;
7500 /* totals[RED]= extractTotals[0][RED]+extractTotals[1][RED];
7501 * totals[RED]/= 2.0;
7502 */
7503 for (kk = 0; kk < BOX2; kk++) {
7504 totals[cc]+= extractTotals[kk][cc];
7505 }
7506 totals[cc]/= (float)BOX2;
7507 } /* for cc */
7508
7509 (*shovePackedPixel)(totals,outIndex,dataOut);
7510 outIndex++;
7511 /* skip over to next group of 2 */
7512 src+= imageSizeInBytes + imageSizeInBytes;
7513 } /* for ii */
7514 }
7515 else if (height == 1) { /* horizontal slice viewed from top */
7516 assert(width != 1);
7517
7518 for (ii= 0; ii< halfDepth; ii++) {
7519 for (jj= 0; jj< halfWidth; jj++) {
7520 float totals[4];
7521 float extractTotals[BOX4][4];
7522 int cc;
7523
7524 (*extractPackedPixel)(isSwap,src,
7525 &extractTotals[0][0]);
7526 (*extractPackedPixel)(isSwap,(src+pixelSizeInBytes),
7527 &extractTotals[1][0]);
7528 (*extractPackedPixel)(isSwap,(src+imageSizeInBytes),
7529 &extractTotals[2][0]);
7530 (*extractPackedPixel)(isSwap,
7531 (src+imageSizeInBytes+pixelSizeInBytes),
7532 &extractTotals[3][0]);
7533 for (cc = 0; cc < components; cc++) {
7534 int kk;
7535
7536 /* grab 4 pixels to average */
7537 totals[cc]= 0.0;
7538 /* totals[RED]= extractTotals[0][RED]+extractTotals[1][RED]+
7539 * extractTotals[2][RED]+extractTotals[3][RED];
7540 * totals[RED]/= 4.0;
7541 */
7542 for (kk = 0; kk < BOX4; kk++) {
7543 totals[cc]+= extractTotals[kk][cc];
7544 }
7545 totals[cc]/= (float)BOX4;
7546 }
7547 (*shovePackedPixel)(totals,outIndex,dataOut);
7548
7549 outIndex++;
7550 /* skip over to next horizontal square of 4 */
7551 src+= imageSizeInBytes + imageSizeInBytes;
7552 }
7553 }
7554
7555 /* assert() */
7556 }
7557 else if (width == 1) { /* vertical slice viewed from top */
7558 assert(height != 1);
7559
7560 for (ii= 0; ii< halfDepth; ii++) {
7561 for (jj= 0; jj< halfHeight; jj++) {
7562 float totals[4];
7563 float extractTotals[BOX4][4];
7564 int cc;
7565
7566 (*extractPackedPixel)(isSwap,src,
7567 &extractTotals[0][0]);
7568 (*extractPackedPixel)(isSwap,(src+rowSizeInBytes),
7569 &extractTotals[1][0]);
7570 (*extractPackedPixel)(isSwap,(src+imageSizeInBytes),
7571 &extractTotals[2][0]);
7572 (*extractPackedPixel)(isSwap,
7573 (src+imageSizeInBytes+rowSizeInBytes),
7574 &extractTotals[3][0]);
7575 for (cc = 0; cc < components; cc++) {
7576 int kk;
7577
7578 /* grab 4 pixels to average */
7579 totals[cc]= 0.0;
7580 /* totals[RED]= extractTotals[0][RED]+extractTotals[1][RED]+
7581 * extractTotals[2][RED]+extractTotals[3][RED];
7582 * totals[RED]/= 4.0;
7583 */
7584 for (kk = 0; kk < BOX4; kk++) {
7585 totals[cc]+= extractTotals[kk][cc];
7586 }
7587 totals[cc]/= (float)BOX4;
7588 }
7589 (*shovePackedPixel)(totals,outIndex,dataOut);
7590
7591 outIndex++;
7592
7593 /* skip over to next vertical square of 4 */
7594 src+= imageSizeInBytes + imageSizeInBytes;
7595 }
7596 }
7597 /* assert() */
7598 }
7599
7600 } /* halveImagePackedPixelSlice() */
7601
7602 static void halveImagePackedPixel3D(int components,
7603 void (*extractPackedPixel)
7604 (int, const void *,GLfloat []),
7605 void (*shovePackedPixel)
7606 (const GLfloat [],int, void *),
7607 GLint width, GLint height, GLint depth,
7608 const void *dataIn, void *dataOut,
7609 GLint pixelSizeInBytes,
7610 GLint rowSizeInBytes,
7611 GLint imageSizeInBytes,
7612 GLint isSwap)
7613 {
7614 if (depth == 1) {
7615 assert(1 <= width && 1 <= height);
7616
7617 halveImagePackedPixel(components,extractPackedPixel,shovePackedPixel,
7618 width,height,dataIn,dataOut,pixelSizeInBytes,
7619 rowSizeInBytes,isSwap);
7620 return;
7621 }
7622 /* a horizontal or vertical slice viewed from top */
7623 else if (width == 1 || height == 1) {
7624 assert(1 <= depth);
7625
7626 halveImagePackedPixelSlice(components,
7627 extractPackedPixel,shovePackedPixel,
7628 width, height, depth, dataIn, dataOut,
7629 pixelSizeInBytes, rowSizeInBytes,
7630 imageSizeInBytes, isSwap);
7631 return;
7632 }
7633 {
7634 int ii, jj, dd;
7635
7636 int halfWidth= width / 2;
7637 int halfHeight= height / 2;
7638 int halfDepth= depth / 2;
7639 const char *src= (const char *) dataIn;
7640 int padBytes= rowSizeInBytes - (width*pixelSizeInBytes);
7641 int outIndex= 0;
7642
7643 for (dd= 0; dd < halfDepth; dd++) {
7644 for (ii= 0; ii< halfHeight; ii++) {
7645 for (jj= 0; jj< halfWidth; jj++) {
7646 #define BOX8 8
7647 float totals[4]; /* 4 is maximum components */
7648 float extractTotals[BOX8][4]; /* 4 is maximum components */
7649 int cc;
7650
7651 (*extractPackedPixel)(isSwap,src,
7652 &extractTotals[0][0]);
7653 (*extractPackedPixel)(isSwap,(src+pixelSizeInBytes),
7654 &extractTotals[1][0]);
7655 (*extractPackedPixel)(isSwap,(src+rowSizeInBytes),
7656 &extractTotals[2][0]);
7657 (*extractPackedPixel)(isSwap,
7658 (src+rowSizeInBytes+pixelSizeInBytes),
7659 &extractTotals[3][0]);
7660
7661 (*extractPackedPixel)(isSwap,(src+imageSizeInBytes),
7662 &extractTotals[4][0]);
7663 (*extractPackedPixel)(isSwap,(src+pixelSizeInBytes+imageSizeInBytes),
7664 &extractTotals[5][0]);
7665 (*extractPackedPixel)(isSwap,(src+rowSizeInBytes+imageSizeInBytes),
7666 &extractTotals[6][0]);
7667 (*extractPackedPixel)(isSwap,
7668 (src+rowSizeInBytes+pixelSizeInBytes+imageSizeInBytes),
7669 &extractTotals[7][0]);
7670 for (cc = 0; cc < components; cc++) {
7671 int kk;
7672
7673 /* grab 8 pixels to average */
7674 totals[cc]= 0.0;
7675 /* totals[RED]= extractTotals[0][RED]+extractTotals[1][RED]+
7676 * extractTotals[2][RED]+extractTotals[3][RED]+
7677 * extractTotals[4][RED]+extractTotals[5][RED]+
7678 * extractTotals[6][RED]+extractTotals[7][RED];
7679 * totals[RED]/= 8.0;
7680 */
7681 for (kk = 0; kk < BOX8; kk++) {
7682 totals[cc]+= extractTotals[kk][cc];
7683 }
7684 totals[cc]/= (float)BOX8;
7685 }
7686 (*shovePackedPixel)(totals,outIndex,dataOut);
7687
7688 outIndex++;
7689 /* skip over to next square of 4 */
7690 src+= pixelSizeInBytes + pixelSizeInBytes;
7691 }
7692 /* skip past pad bytes, if any, to get to next row */
7693 src+= padBytes;
7694
7695 /* src is at beginning of a row here, but it's the second row of
7696 * the square block of 4 pixels that we just worked on so we
7697 * need to go one more row.
7698 * i.e.,
7699 * OO...
7700 * here -->OO...
7701 * but want -->OO...
7702 * OO...
7703 * ...
7704 */
7705 src+= rowSizeInBytes;
7706 }
7707
7708 src+= imageSizeInBytes;
7709 } /* for dd */
7710
7711 /* both pointers must reach one byte after the end */
7712 assert(src == &((const char *)dataIn)[rowSizeInBytes*height*depth]);
7713 assert(outIndex == halfWidth * halfHeight * halfDepth);
7714 } /* for dd */
7715
7716 } /* halveImagePackedPixel3D() */
7717
7718 static int gluBuild3DMipmapLevelsCore(GLenum target, GLint internalFormat,
7719 GLsizei width,
7720 GLsizei height,
7721 GLsizei depth,
7722 GLsizei widthPowerOf2,
7723 GLsizei heightPowerOf2,
7724 GLsizei depthPowerOf2,
7725 GLenum format, GLenum type,
7726 GLint userLevel,
7727 GLint baseLevel,GLint maxLevel,
7728 const void *data)
7729 {
7730 GLint newWidth, newHeight, newDepth;
7731 GLint level, levels;
7732 const void *usersImage;
7733 void *srcImage, *dstImage;
7734 __GLU_INIT_SWAP_IMAGE;
7735 GLint memReq;
7736 GLint cmpts;
7737
7738 GLint myswapBytes, groupsPerLine, elementSize, groupSize;
7739 GLint rowsPerImage, imageSize;
7740 GLint rowSize, padding;
7741 PixelStorageModes psm;
7742
7743 assert(checkMipmapArgs(internalFormat,format,type) == 0);
7744 assert(width >= 1 && height >= 1 && depth >= 1);
7745 assert(type != GL_BITMAP);
7746
7747 srcImage = dstImage = NULL;
7748
7749 newWidth= widthPowerOf2;
7750 newHeight= heightPowerOf2;
7751 newDepth= depthPowerOf2;
7752 levels = computeLog(newWidth);
7753 level = computeLog(newHeight);
7754 if (level > levels) levels=level;
7755 level = computeLog(newDepth);
7756 if (level > levels) levels=level;
7757
7758 levels+= userLevel;
7759
7760 retrieveStoreModes3D(&psm);
7761 myswapBytes = psm.unpack_swap_bytes;
7762 cmpts = elements_per_group(format,type);
7763 if (psm.unpack_row_length > 0) {
7764 groupsPerLine = psm.unpack_row_length;
7765 } else {
7766 groupsPerLine = width;
7767 }
7768
7769 elementSize = bytes_per_element(type);
7770 groupSize = elementSize * cmpts;
7771 if (elementSize == 1) myswapBytes = 0;
7772
7773 /* 3dstuff begin */
7774 if (psm.unpack_image_height > 0) {
7775 rowsPerImage= psm.unpack_image_height;
7776 }
7777 else {
7778 rowsPerImage= height;
7779 }
7780
7781 /* 3dstuff end */
7782 rowSize = groupsPerLine * groupSize;
7783 padding = (rowSize % psm.unpack_alignment);
7784 if (padding) {
7785 rowSize += psm.unpack_alignment - padding;
7786 }
7787
7788 imageSize= rowsPerImage * rowSize; /* 3dstuff */
7789
7790 usersImage = (const GLubyte *)data + psm.unpack_skip_rows * rowSize +
7791 psm.unpack_skip_pixels * groupSize +
7792 /* 3dstuff */
7793 psm.unpack_skip_images * imageSize;
7794
7795 glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
7796 glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
7797 glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
7798 glPixelStorei(GL_UNPACK_SKIP_IMAGES, 0);
7799 glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, 0);
7800
7801 level = userLevel;
7802
7803 if (width == newWidth && height == newHeight && depth == newDepth) {
7804 /* Use usersImage for level userLevel */
7805 if (baseLevel <= level && level <= maxLevel) {
7806 gluTexImage3D(target, level, internalFormat, width,
7807 height, depth, 0, format, type,
7808 usersImage);
7809 }
7810 if(levels == 0) { /* we're done. clean up and return */
7811 glPixelStorei(GL_UNPACK_ALIGNMENT, psm.unpack_alignment);
7812 glPixelStorei(GL_UNPACK_SKIP_ROWS, psm.unpack_skip_rows);
7813 glPixelStorei(GL_UNPACK_SKIP_PIXELS, psm.unpack_skip_pixels);
7814 glPixelStorei(GL_UNPACK_ROW_LENGTH, psm.unpack_row_length);
7815 glPixelStorei(GL_UNPACK_SWAP_BYTES, psm.unpack_swap_bytes);
7816 glPixelStorei(GL_UNPACK_SKIP_IMAGES, psm.unpack_skip_images);
7817 glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, psm.unpack_image_height);
7818 return 0;
7819 }
7820 {
7821 int nextWidth= newWidth/2;
7822 int nextHeight= newHeight/2;
7823 int nextDepth= newDepth/2;
7824
7825 /* clamp to 1 */
7826 if (nextWidth < 1) nextWidth= 1;
7827 if (nextHeight < 1) nextHeight= 1;
7828 if (nextDepth < 1) nextDepth= 1;
7829 memReq = imageSize3D(nextWidth, nextHeight, nextDepth, format, type);
7830 }
7831 switch(type) {
7832 case GL_UNSIGNED_BYTE:
7833 dstImage = (GLubyte *)malloc(memReq);
7834 break;
7835 case GL_BYTE:
7836 dstImage = (GLbyte *)malloc(memReq);
7837 break;
7838 case GL_UNSIGNED_SHORT:
7839 dstImage = (GLushort *)malloc(memReq);
7840 break;
7841 case GL_SHORT:
7842 dstImage = (GLshort *)malloc(memReq);
7843 break;
7844 case GL_UNSIGNED_INT:
7845 dstImage = (GLuint *)malloc(memReq);
7846 break;
7847 case GL_INT:
7848 dstImage = (GLint *)malloc(memReq);
7849 break;
7850 case GL_FLOAT:
7851 dstImage = (GLfloat *)malloc(memReq);
7852 break;
7853 case GL_UNSIGNED_BYTE_3_3_2:
7854 case GL_UNSIGNED_BYTE_2_3_3_REV:
7855 dstImage = (GLubyte *)malloc(memReq);
7856 break;
7857 case GL_UNSIGNED_SHORT_5_6_5:
7858 case GL_UNSIGNED_SHORT_5_6_5_REV:
7859 case GL_UNSIGNED_SHORT_4_4_4_4:
7860 case GL_UNSIGNED_SHORT_4_4_4_4_REV:
7861 case GL_UNSIGNED_SHORT_5_5_5_1:
7862 case GL_UNSIGNED_SHORT_1_5_5_5_REV:
7863 dstImage = (GLushort *)malloc(memReq);
7864 break;
7865 case GL_UNSIGNED_INT_8_8_8_8:
7866 case GL_UNSIGNED_INT_8_8_8_8_REV:
7867 case GL_UNSIGNED_INT_10_10_10_2:
7868 case GL_UNSIGNED_INT_2_10_10_10_REV:
7869 dstImage = (GLuint *)malloc(memReq);
7870 break;
7871 default:
7872 return GLU_INVALID_ENUM; /* assertion */
7873 }
7874 if (dstImage == NULL) {
7875 glPixelStorei(GL_UNPACK_ALIGNMENT, psm.unpack_alignment);
7876 glPixelStorei(GL_UNPACK_SKIP_ROWS, psm.unpack_skip_rows);
7877 glPixelStorei(GL_UNPACK_SKIP_PIXELS, psm.unpack_skip_pixels);
7878 glPixelStorei(GL_UNPACK_ROW_LENGTH, psm.unpack_row_length);
7879 glPixelStorei(GL_UNPACK_SWAP_BYTES, psm.unpack_swap_bytes);
7880 glPixelStorei(GL_UNPACK_SKIP_IMAGES, psm.unpack_skip_images);
7881 glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, psm.unpack_image_height);
7882 return GLU_OUT_OF_MEMORY;
7883 }
7884 else
7885 switch(type) {
7886 case GL_UNSIGNED_BYTE:
7887 if (depth > 1) {
7888 halveImage3D(cmpts,extractUbyte,shoveUbyte,
7889 width,height,depth,
7890 usersImage,dstImage,elementSize,groupSize,rowSize,
7891 imageSize,myswapBytes);
7892 }
7893 else {
7894 halveImage_ubyte(cmpts,width,height,usersImage,dstImage,
7895 elementSize,rowSize,groupSize);
7896 }
7897 break;
7898 case GL_BYTE:
7899 if (depth > 1) {
7900 halveImage3D(cmpts,extractSbyte,shoveSbyte,
7901 width,height,depth,
7902 usersImage,dstImage,elementSize,groupSize,rowSize,
7903 imageSize,myswapBytes);
7904 }
7905 else {
7906 halveImage_byte(cmpts,width,height,usersImage,dstImage,
7907 elementSize,rowSize,groupSize);
7908 }
7909 break;
7910 case GL_UNSIGNED_SHORT:
7911 if (depth > 1) {
7912 halveImage3D(cmpts,extractUshort,shoveUshort,
7913 width,height,depth,
7914 usersImage,dstImage,elementSize,groupSize,rowSize,
7915 imageSize,myswapBytes);
7916 }
7917 else {
7918 halveImage_ushort(cmpts,width,height,usersImage,dstImage,
7919 elementSize,rowSize,groupSize,myswapBytes);
7920 }
7921 break;
7922 case GL_SHORT:
7923 if (depth > 1) {
7924 halveImage3D(cmpts,extractSshort,shoveSshort,
7925 width,height,depth,
7926 usersImage,dstImage,elementSize,groupSize,rowSize,
7927 imageSize,myswapBytes);
7928 }
7929 else {
7930 halveImage_short(cmpts,width,height,usersImage,dstImage,
7931 elementSize,rowSize,groupSize,myswapBytes);
7932 }
7933 break;
7934 case GL_UNSIGNED_INT:
7935 if (depth > 1) {
7936 halveImage3D(cmpts,extractUint,shoveUint,
7937 width,height,depth,
7938 usersImage,dstImage,elementSize,groupSize,rowSize,
7939 imageSize,myswapBytes);
7940 }
7941 else {
7942 halveImage_uint(cmpts,width,height,usersImage,dstImage,
7943 elementSize,rowSize,groupSize,myswapBytes);
7944 }
7945 break;
7946 case GL_INT:
7947 if (depth > 1) {
7948 halveImage3D(cmpts,extractSint,shoveSint,
7949 width,height,depth,
7950 usersImage,dstImage,elementSize,groupSize,rowSize,
7951 imageSize,myswapBytes);
7952 }
7953 else {
7954 halveImage_int(cmpts,width,height,usersImage,dstImage,
7955 elementSize,rowSize,groupSize,myswapBytes);
7956 }
7957 break;
7958 case GL_FLOAT:
7959 if (depth > 1 ) {
7960 halveImage3D(cmpts,extractFloat,shoveFloat,
7961 width,height,depth,
7962 usersImage,dstImage,elementSize,groupSize,rowSize,
7963 imageSize,myswapBytes);
7964 }
7965 else {
7966 halveImage_float(cmpts,width,height,usersImage,dstImage,
7967 elementSize,rowSize,groupSize,myswapBytes);
7968 }
7969 break;
7970 case GL_UNSIGNED_BYTE_3_3_2:
7971 assert(format == GL_RGB);
7972 halveImagePackedPixel3D(3,extract332,shove332,
7973 width,height,depth,usersImage,dstImage,
7974 elementSize,rowSize,imageSize,myswapBytes);
7975 break;
7976 case GL_UNSIGNED_BYTE_2_3_3_REV:
7977 assert(format == GL_RGB);
7978 halveImagePackedPixel3D(3,extract233rev,shove233rev,
7979 width,height,depth,usersImage,dstImage,
7980 elementSize,rowSize,imageSize,myswapBytes);
7981 break;
7982 case GL_UNSIGNED_SHORT_5_6_5:
7983 halveImagePackedPixel3D(3,extract565,shove565,
7984 width,height,depth,usersImage,dstImage,
7985 elementSize,rowSize,imageSize,myswapBytes);
7986 break;
7987 case GL_UNSIGNED_SHORT_5_6_5_REV:
7988 halveImagePackedPixel3D(3,extract565rev,shove565rev,
7989 width,height,depth,usersImage,dstImage,
7990 elementSize,rowSize,imageSize,myswapBytes);
7991 break;
7992 case GL_UNSIGNED_SHORT_4_4_4_4:
7993 halveImagePackedPixel3D(4,extract4444,shove4444,
7994 width,height,depth,usersImage,dstImage,
7995 elementSize,rowSize,imageSize,myswapBytes);
7996 break;
7997 case GL_UNSIGNED_SHORT_4_4_4_4_REV:
7998 halveImagePackedPixel3D(4,extract4444rev,shove4444rev,
7999 width,height,depth,usersImage,dstImage,
8000 elementSize,rowSize,imageSize,myswapBytes);
8001 break;
8002 case GL_UNSIGNED_SHORT_5_5_5_1:
8003 halveImagePackedPixel3D(4,extract5551,shove5551,
8004 width,height,depth,usersImage,dstImage,
8005 elementSize,rowSize,imageSize,myswapBytes);
8006 break;
8007 case GL_UNSIGNED_SHORT_1_5_5_5_REV:
8008 halveImagePackedPixel3D(4,extract1555rev,shove1555rev,
8009 width,height,depth,usersImage,dstImage,
8010 elementSize,rowSize,imageSize,myswapBytes);
8011 break;
8012 case GL_UNSIGNED_INT_8_8_8_8:
8013 halveImagePackedPixel3D(4,extract8888,shove8888,
8014 width,height,depth,usersImage,dstImage,
8015 elementSize,rowSize,imageSize,myswapBytes);
8016 break;
8017 case GL_UNSIGNED_INT_8_8_8_8_REV:
8018 halveImagePackedPixel3D(4,extract8888rev,shove8888rev,
8019 width,height,depth,usersImage,dstImage,
8020 elementSize,rowSize,imageSize,myswapBytes);
8021 break;
8022 case GL_UNSIGNED_INT_10_10_10_2:
8023 halveImagePackedPixel3D(4,extract1010102,shove1010102,
8024 width,height,depth,usersImage,dstImage,
8025 elementSize,rowSize,imageSize,myswapBytes);
8026 break;
8027 case GL_UNSIGNED_INT_2_10_10_10_REV:
8028 halveImagePackedPixel3D(4,extract2101010rev,shove2101010rev,
8029 width,height,depth,usersImage,dstImage,
8030 elementSize,rowSize,imageSize,myswapBytes);
8031 break;
8032 default:
8033 assert(0);
8034 break;
8035 }
8036 newWidth = width/2;
8037 newHeight = height/2;
8038 newDepth = depth/2;
8039 /* clamp to 1 */
8040 if (newWidth < 1) newWidth= 1;
8041 if (newHeight < 1) newHeight= 1;
8042 if (newDepth < 1) newDepth= 1;
8043
8044 myswapBytes = 0;
8045 rowSize = newWidth * groupSize;
8046 imageSize= rowSize * newHeight; /* 3dstuff */
8047 memReq = imageSize3D(newWidth, newHeight, newDepth, format, type);
8048 /* Swap srcImage and dstImage */
8049 __GLU_SWAP_IMAGE(srcImage,dstImage);
8050 switch(type) {
8051 case GL_UNSIGNED_BYTE:
8052 dstImage = (GLubyte *)malloc(memReq);
8053 break;
8054 case GL_BYTE:
8055 dstImage = (GLbyte *)malloc(memReq);
8056 break;
8057 case GL_UNSIGNED_SHORT:
8058 dstImage = (GLushort *)malloc(memReq);
8059 break;
8060 case GL_SHORT:
8061 dstImage = (GLshort *)malloc(memReq);
8062 break;
8063 case GL_UNSIGNED_INT:
8064 dstImage = (GLuint *)malloc(memReq);
8065 break;
8066 case GL_INT:
8067 dstImage = (GLint *)malloc(memReq);
8068 break;
8069 case GL_FLOAT:
8070 dstImage = (GLfloat *)malloc(memReq);
8071 break;
8072 case GL_UNSIGNED_BYTE_3_3_2:
8073 case GL_UNSIGNED_BYTE_2_3_3_REV:
8074 dstImage = (GLubyte *)malloc(memReq);
8075 break;
8076 case GL_UNSIGNED_SHORT_5_6_5:
8077 case GL_UNSIGNED_SHORT_5_6_5_REV:
8078 case GL_UNSIGNED_SHORT_4_4_4_4:
8079 case GL_UNSIGNED_SHORT_4_4_4_4_REV:
8080 case GL_UNSIGNED_SHORT_5_5_5_1:
8081 case GL_UNSIGNED_SHORT_1_5_5_5_REV:
8082 dstImage = (GLushort *)malloc(memReq);
8083 break;
8084 case GL_UNSIGNED_INT_8_8_8_8:
8085 case GL_UNSIGNED_INT_8_8_8_8_REV:
8086 case GL_UNSIGNED_INT_10_10_10_2:
8087 case GL_UNSIGNED_INT_2_10_10_10_REV:
8088 dstImage = (GLuint *)malloc(memReq);
8089 break;
8090 default:
8091 return GLU_INVALID_ENUM; /* assertion */
8092 }
8093 if (dstImage == NULL) {
8094 glPixelStorei(GL_UNPACK_ALIGNMENT, psm.unpack_alignment);
8095 glPixelStorei(GL_UNPACK_SKIP_ROWS, psm.unpack_skip_rows);
8096 glPixelStorei(GL_UNPACK_SKIP_PIXELS, psm.unpack_skip_pixels);
8097 glPixelStorei(GL_UNPACK_ROW_LENGTH, psm.unpack_row_length);
8098 glPixelStorei(GL_UNPACK_SWAP_BYTES, psm.unpack_swap_bytes);
8099 glPixelStorei(GL_UNPACK_SKIP_IMAGES, psm.unpack_skip_images);
8100 glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, psm.unpack_image_height);
8101 return GLU_OUT_OF_MEMORY;
8102 }
8103 /* level userLevel+1 is in srcImage; level userLevel already saved */
8104 level = userLevel+1;
8105 } else {/* user's image is *not* nice power-of-2 sized square */
8106 memReq = imageSize3D(newWidth, newHeight, newDepth, format, type);
8107 switch(type) {
8108 case GL_UNSIGNED_BYTE:
8109 dstImage = (GLubyte *)malloc(memReq);
8110 break;
8111 case GL_BYTE:
8112 dstImage = (GLbyte *)malloc(memReq);
8113 break;
8114 case GL_UNSIGNED_SHORT:
8115 dstImage = (GLushort *)malloc(memReq);
8116 break;
8117 case GL_SHORT:
8118 dstImage = (GLshort *)malloc(memReq);
8119 break;
8120 case GL_UNSIGNED_INT:
8121 dstImage = (GLuint *)malloc(memReq);
8122 break;
8123 case GL_INT:
8124 dstImage = (GLint *)malloc(memReq);
8125 break;
8126 case GL_FLOAT:
8127 dstImage = (GLfloat *)malloc(memReq);
8128 break;
8129 case GL_UNSIGNED_BYTE_3_3_2:
8130 case GL_UNSIGNED_BYTE_2_3_3_REV:
8131 dstImage = (GLubyte *)malloc(memReq);
8132 break;
8133 case GL_UNSIGNED_SHORT_5_6_5:
8134 case GL_UNSIGNED_SHORT_5_6_5_REV:
8135 case GL_UNSIGNED_SHORT_4_4_4_4:
8136 case GL_UNSIGNED_SHORT_4_4_4_4_REV:
8137 case GL_UNSIGNED_SHORT_5_5_5_1:
8138 case GL_UNSIGNED_SHORT_1_5_5_5_REV:
8139 dstImage = (GLushort *)malloc(memReq);
8140 break;
8141 case GL_UNSIGNED_INT_8_8_8_8:
8142 case GL_UNSIGNED_INT_8_8_8_8_REV:
8143 case GL_UNSIGNED_INT_10_10_10_2:
8144 case GL_UNSIGNED_INT_2_10_10_10_REV:
8145 dstImage = (GLuint *)malloc(memReq);
8146 break;
8147 default:
8148 return GLU_INVALID_ENUM; /* assertion */
8149 }
8150
8151 if (dstImage == NULL) {
8152 glPixelStorei(GL_UNPACK_ALIGNMENT, psm.unpack_alignment);
8153 glPixelStorei(GL_UNPACK_SKIP_ROWS, psm.unpack_skip_rows);
8154 glPixelStorei(GL_UNPACK_SKIP_PIXELS, psm.unpack_skip_pixels);
8155 glPixelStorei(GL_UNPACK_ROW_LENGTH, psm.unpack_row_length);
8156 glPixelStorei(GL_UNPACK_SWAP_BYTES, psm.unpack_swap_bytes);
8157 glPixelStorei(GL_UNPACK_SKIP_IMAGES, psm.unpack_skip_images);
8158 glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, psm.unpack_image_height);
8159 return GLU_OUT_OF_MEMORY;
8160 }
8161 /*printf("Build3DMipmaps(): ScaleImage3D %d %d %d->%d %d %d\n",
8162 width,height,depth,newWidth,newHeight,newDepth);*/
8163
8164 gluScaleImage3D(format, width, height, depth, type, usersImage,
8165 newWidth, newHeight, newDepth, type, dstImage);
8166
8167 myswapBytes = 0;
8168 rowSize = newWidth * groupSize;
8169 imageSize = rowSize * newHeight; /* 3dstuff */
8170 /* Swap dstImage and srcImage */
8171 __GLU_SWAP_IMAGE(srcImage,dstImage);
8172
8173 if(levels != 0) { /* use as little memory as possible */
8174 {
8175 int nextWidth= newWidth/2;
8176 int nextHeight= newHeight/2;
8177 int nextDepth= newDepth/2;
8178 if (nextWidth < 1) nextWidth= 1;
8179 if (nextHeight < 1) nextHeight= 1;
8180 if (nextDepth < 1) nextDepth= 1;
8181
8182 memReq = imageSize3D(nextWidth, nextHeight, nextDepth, format, type);
8183 }
8184 switch(type) {
8185 case GL_UNSIGNED_BYTE:
8186 dstImage = (GLubyte *)malloc(memReq);
8187 break;
8188 case GL_BYTE:
8189 dstImage = (GLbyte *)malloc(memReq);
8190 break;
8191 case GL_UNSIGNED_SHORT:
8192 dstImage = (GLushort *)malloc(memReq);
8193 break;
8194 case GL_SHORT:
8195 dstImage = (GLshort *)malloc(memReq);
8196 break;
8197 case GL_UNSIGNED_INT:
8198 dstImage = (GLuint *)malloc(memReq);
8199 break;
8200 case GL_INT:
8201 dstImage = (GLint *)malloc(memReq);
8202 break;
8203 case GL_FLOAT:
8204 dstImage = (GLfloat *)malloc(memReq);
8205 break;
8206 case GL_UNSIGNED_BYTE_3_3_2:
8207 case GL_UNSIGNED_BYTE_2_3_3_REV:
8208 dstImage = (GLubyte *)malloc(memReq);
8209 break;
8210 case GL_UNSIGNED_SHORT_5_6_5:
8211 case GL_UNSIGNED_SHORT_5_6_5_REV:
8212 case GL_UNSIGNED_SHORT_4_4_4_4:
8213 case GL_UNSIGNED_SHORT_4_4_4_4_REV:
8214 case GL_UNSIGNED_SHORT_5_5_5_1:
8215 case GL_UNSIGNED_SHORT_1_5_5_5_REV:
8216 dstImage = (GLushort *)malloc(memReq);
8217 break;
8218 case GL_UNSIGNED_INT_8_8_8_8:
8219 case GL_UNSIGNED_INT_8_8_8_8_REV:
8220 case GL_UNSIGNED_INT_10_10_10_2:
8221 case GL_UNSIGNED_INT_2_10_10_10_REV:
8222 dstImage = (GLuint *)malloc(memReq);
8223 break;
8224 default:
8225 return GLU_INVALID_ENUM; /* assertion */
8226 }
8227 if (dstImage == NULL) {
8228 glPixelStorei(GL_UNPACK_ALIGNMENT, psm.unpack_alignment);
8229 glPixelStorei(GL_UNPACK_SKIP_ROWS, psm.unpack_skip_rows);
8230 glPixelStorei(GL_UNPACK_SKIP_PIXELS, psm.unpack_skip_pixels);
8231 glPixelStorei(GL_UNPACK_ROW_LENGTH, psm.unpack_row_length);
8232 glPixelStorei(GL_UNPACK_SWAP_BYTES, psm.unpack_swap_bytes);
8233 glPixelStorei(GL_UNPACK_SKIP_IMAGES, psm.unpack_skip_images);
8234 glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, psm.unpack_image_height);
8235 return GLU_OUT_OF_MEMORY;
8236 }
8237 }
8238 /* level userLevel is in srcImage; nothing saved yet */
8239 level = userLevel;
8240 }
8241
8242 glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE);
8243 if (baseLevel <= level && level <= maxLevel) {
8244 gluTexImage3D(target, level, internalFormat, newWidth, newHeight, newDepth,
8245 0,format, type, (void *)srcImage);
8246 }
8247 level++; /* update current level for the loop */
8248 for (; level <= levels; level++) {
8249 switch(type) {
8250 case GL_UNSIGNED_BYTE:
8251 if (newDepth > 1) {
8252 halveImage3D(cmpts,extractUbyte,shoveUbyte,
8253 newWidth,newHeight,newDepth,
8254 srcImage,dstImage,elementSize,groupSize,rowSize,
8255 imageSize,myswapBytes);
8256 }
8257 else {
8258 halveImage_ubyte(cmpts,newWidth,newHeight,srcImage,dstImage,
8259 elementSize,rowSize,groupSize);
8260 }
8261 break;
8262 case GL_BYTE:
8263 if (newDepth > 1) {
8264 halveImage3D(cmpts,extractSbyte,shoveSbyte,
8265 newWidth,newHeight,newDepth,
8266 srcImage,dstImage,elementSize,groupSize,rowSize,
8267 imageSize,myswapBytes);
8268 }
8269 else {
8270 halveImage_byte(cmpts,newWidth,newHeight,srcImage,dstImage,
8271 elementSize,rowSize,groupSize);
8272 }
8273 break;
8274 case GL_UNSIGNED_SHORT:
8275 if (newDepth > 1) {
8276 halveImage3D(cmpts,extractUshort,shoveUshort,
8277 newWidth,newHeight,newDepth,
8278 srcImage,dstImage,elementSize,groupSize,rowSize,
8279 imageSize,myswapBytes);
8280 }
8281 else {
8282 halveImage_ushort(cmpts,newWidth,newHeight,srcImage,dstImage,
8283 elementSize,rowSize,groupSize,myswapBytes);
8284 }
8285 break;
8286 case GL_SHORT:
8287 if (newDepth > 1) {
8288 halveImage3D(cmpts,extractSshort,shoveSshort,
8289 newWidth,newHeight,newDepth,
8290 srcImage,dstImage,elementSize,groupSize,rowSize,
8291 imageSize,myswapBytes);
8292 }
8293 else {
8294 halveImage_short(cmpts,newWidth,newHeight,srcImage,dstImage,
8295 elementSize,rowSize,groupSize,myswapBytes);
8296 }
8297 break;
8298 case GL_UNSIGNED_INT:
8299 if (newDepth > 1) {
8300 halveImage3D(cmpts,extractUint,shoveUint,
8301 newWidth,newHeight,newDepth,
8302 srcImage,dstImage,elementSize,groupSize,rowSize,
8303 imageSize,myswapBytes);
8304 }
8305 else {
8306 halveImage_uint(cmpts,newWidth,newHeight,srcImage,dstImage,
8307 elementSize,rowSize,groupSize,myswapBytes);
8308 }
8309 break;
8310 case GL_INT:
8311 if (newDepth > 1) {
8312 halveImage3D(cmpts,extractSint,shoveSint,
8313 newWidth,newHeight,newDepth,
8314 srcImage,dstImage,elementSize,groupSize,rowSize,
8315 imageSize,myswapBytes);
8316 }
8317 else {
8318 halveImage_int(cmpts,newWidth,newHeight,srcImage,dstImage,
8319 elementSize,rowSize,groupSize,myswapBytes);
8320 }
8321 break;
8322 case GL_FLOAT:
8323 if (newDepth > 1) {
8324 halveImage3D(cmpts,extractFloat,shoveFloat,
8325 newWidth,newHeight,newDepth,
8326 srcImage,dstImage,elementSize,groupSize,rowSize,
8327 imageSize,myswapBytes);
8328 }
8329 else {
8330 halveImage_float(cmpts,newWidth,newHeight,srcImage,dstImage,
8331 elementSize,rowSize,groupSize,myswapBytes);
8332 }
8333 break;
8334 case GL_UNSIGNED_BYTE_3_3_2:
8335 halveImagePackedPixel3D(3,extract332,shove332,
8336 newWidth,newHeight,newDepth,
8337 srcImage,dstImage,elementSize,rowSize,
8338 imageSize,myswapBytes);
8339 break;
8340 case GL_UNSIGNED_BYTE_2_3_3_REV:
8341 halveImagePackedPixel3D(3,extract233rev,shove233rev,
8342 newWidth,newHeight,newDepth,
8343 srcImage,dstImage,elementSize,rowSize,
8344 imageSize,myswapBytes);
8345 break;
8346 case GL_UNSIGNED_SHORT_5_6_5:
8347 halveImagePackedPixel3D(3,extract565,shove565,
8348 newWidth,newHeight,newDepth,
8349 srcImage,dstImage,elementSize,rowSize,
8350 imageSize,myswapBytes);
8351 break;
8352 case GL_UNSIGNED_SHORT_5_6_5_REV:
8353 halveImagePackedPixel3D(3,extract565rev,shove565rev,
8354 newWidth,newHeight,newDepth,
8355 srcImage,dstImage,elementSize,rowSize,
8356 imageSize,myswapBytes);
8357 break;
8358 case GL_UNSIGNED_SHORT_4_4_4_4:
8359 halveImagePackedPixel3D(4,extract4444,shove4444,
8360 newWidth,newHeight,newDepth,
8361 srcImage,dstImage,elementSize,rowSize,
8362 imageSize,myswapBytes);
8363 break;
8364 case GL_UNSIGNED_SHORT_4_4_4_4_REV:
8365 halveImagePackedPixel3D(4,extract4444rev,shove4444rev,
8366 newWidth,newHeight,newDepth,
8367 srcImage,dstImage,elementSize,rowSize,
8368 imageSize,myswapBytes);
8369 break;
8370 case GL_UNSIGNED_SHORT_5_5_5_1:
8371 halveImagePackedPixel3D(4,extract5551,shove5551,
8372 newWidth,newHeight,newDepth,
8373 srcImage,dstImage,elementSize,rowSize,
8374 imageSize,myswapBytes);
8375 break;
8376 case GL_UNSIGNED_SHORT_1_5_5_5_REV:
8377 halveImagePackedPixel3D(4,extract1555rev,shove1555rev,
8378 newWidth,newHeight,newDepth,
8379 srcImage,dstImage,elementSize,rowSize,
8380 imageSize,myswapBytes);
8381 break;
8382 case GL_UNSIGNED_INT_8_8_8_8:
8383 halveImagePackedPixel3D(4,extract8888,shove8888,
8384 newWidth,newHeight,newDepth,
8385 srcImage,dstImage,elementSize,rowSize,
8386 imageSize,myswapBytes);
8387 break;
8388 case GL_UNSIGNED_INT_8_8_8_8_REV:
8389 halveImagePackedPixel3D(4,extract8888rev,shove8888rev,
8390 newWidth,newHeight,newDepth,
8391 srcImage,dstImage,elementSize,rowSize,
8392 imageSize,myswapBytes);
8393 break;
8394 case GL_UNSIGNED_INT_10_10_10_2:
8395 halveImagePackedPixel3D(4,extract1010102,shove1010102,
8396 newWidth,newHeight,newDepth,
8397 srcImage,dstImage,elementSize,rowSize,
8398 imageSize,myswapBytes);
8399 break;
8400 case GL_UNSIGNED_INT_2_10_10_10_REV:
8401 halveImagePackedPixel3D(4,extract2101010rev,shove2101010rev,
8402 newWidth,newHeight,newDepth,
8403 srcImage,dstImage,elementSize,rowSize,
8404 imageSize,myswapBytes);
8405 break;
8406 default:
8407 assert(0);
8408 break;
8409 }
8410
8411 __GLU_SWAP_IMAGE(srcImage,dstImage);
8412
8413 if (newWidth > 1) { newWidth /= 2; rowSize /= 2;}
8414 if (newHeight > 1) { newHeight /= 2; imageSize = rowSize * newHeight; }
8415 if (newDepth > 1) newDepth /= 2;
8416 {
8417 /* call tex image with srcImage untouched since it's not padded */
8418 if (baseLevel <= level && level <= maxLevel) {
8419 gluTexImage3D(target, level, internalFormat, newWidth, newHeight,
8420 newDepth,0, format, type, (void *) srcImage);
8421 }
8422 }
8423 } /* for level */
8424 glPixelStorei(GL_UNPACK_ALIGNMENT, psm.unpack_alignment);
8425 glPixelStorei(GL_UNPACK_SKIP_ROWS, psm.unpack_skip_rows);
8426 glPixelStorei(GL_UNPACK_SKIP_PIXELS, psm.unpack_skip_pixels);
8427 glPixelStorei(GL_UNPACK_ROW_LENGTH, psm.unpack_row_length);
8428 glPixelStorei(GL_UNPACK_SWAP_BYTES, psm.unpack_swap_bytes);
8429 glPixelStorei(GL_UNPACK_SKIP_IMAGES, psm.unpack_skip_images);
8430 glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, psm.unpack_image_height);
8431
8432 free(srcImage); /*if you get to here, a srcImage has always been malloc'ed*/
8433 if (dstImage) { /* if it's non-rectangular and only 1 level */
8434 free(dstImage);
8435 }
8436 return 0;
8437 } /* gluBuild3DMipmapLevelsCore() */
8438
8439 GLint GLAPIENTRY
8440 gluBuild3DMipmapLevels(GLenum target, GLint internalFormat,
8441 GLsizei width, GLsizei height, GLsizei depth,
8442 GLenum format, GLenum type,
8443 GLint userLevel, GLint baseLevel, GLint maxLevel,
8444 const void *data)
8445 {
8446 int level, levels;
8447
8448 int rc= checkMipmapArgs(internalFormat,format,type);
8449 if (rc != 0) return rc;
8450
8451 if (width < 1 || height < 1 || depth < 1) {
8452 return GLU_INVALID_VALUE;
8453 }
8454
8455 if(type == GL_BITMAP) {
8456 return GLU_INVALID_ENUM;
8457 }
8458
8459 levels = computeLog(width);
8460 level = computeLog(height);
8461 if (level > levels) levels=level;
8462 level = computeLog(depth);
8463 if (level > levels) levels=level;
8464
8465 levels+= userLevel;
8466 if (!isLegalLevels(userLevel,baseLevel,maxLevel,levels))
8467 return GLU_INVALID_VALUE;
8468
8469 return gluBuild3DMipmapLevelsCore(target, internalFormat,
8470 width, height, depth,
8471 width, height, depth,
8472 format, type,
8473 userLevel, baseLevel, maxLevel,
8474 data);
8475 } /* gluBuild3DMipmapLevels() */
8476
8477 GLint GLAPIENTRY
8478 gluBuild3DMipmaps(GLenum target, GLint internalFormat,
8479 GLsizei width, GLsizei height, GLsizei depth,
8480 GLenum format, GLenum type, const void *data)
8481 {
8482 GLint widthPowerOf2, heightPowerOf2, depthPowerOf2;
8483 int level, levels;
8484
8485 int rc= checkMipmapArgs(internalFormat,format,type);
8486 if (rc != 0) return rc;
8487
8488 if (width < 1 || height < 1 || depth < 1) {
8489 return GLU_INVALID_VALUE;
8490 }
8491
8492 if(type == GL_BITMAP) {
8493 return GLU_INVALID_ENUM;
8494 }
8495
8496 closestFit3D(target,width,height,depth,internalFormat,format,type,
8497 &widthPowerOf2,&heightPowerOf2,&depthPowerOf2);
8498
8499 levels = computeLog(widthPowerOf2);
8500 level = computeLog(heightPowerOf2);
8501 if (level > levels) levels=level;
8502 level = computeLog(depthPowerOf2);
8503 if (level > levels) levels=level;
8504
8505 return gluBuild3DMipmapLevelsCore(target, internalFormat,
8506 width, height, depth,
8507 widthPowerOf2, heightPowerOf2,
8508 depthPowerOf2,
8509 format, type, 0, 0, levels,
8510 data);
8511 } /* gluBuild3DMipmaps() */
8512
8513 static GLdouble extractUbyte(int isSwap, const void *ubyte)
8514 {
8515 isSwap= isSwap; /* turn off warnings */
8516
8517 assert(*((const GLubyte *)ubyte) <= 255);
8518
8519 return (GLdouble)(*((const GLubyte *)ubyte));
8520 } /* extractUbyte() */
8521
8522 static void shoveUbyte(GLdouble value, int index, void *data)
8523 {
8524 assert(0.0 <= value && value < 256.0);
8525
8526 ((GLubyte *)data)[index]= (GLubyte)value;
8527 } /* shoveUbyte() */
8528
8529 static GLdouble extractSbyte(int isSwap, const void *sbyte)
8530 {
8531 isSwap= isSwap; /* turn off warnings */
8532
8533 assert(*((const GLbyte *)sbyte) <= 127);
8534
8535 return (GLdouble)(*((const GLbyte *)sbyte));
8536 } /* extractSbyte() */
8537
8538 static void shoveSbyte(GLdouble value, int index, void *data)
8539 {
8540 ((GLbyte *)data)[index]= (GLbyte)value;
8541 } /* shoveSbyte() */
8542
8543 static GLdouble extractUshort(int isSwap, const void *uitem)
8544 {
8545 GLushort ushort;
8546
8547 if (isSwap) {
8548 ushort= __GLU_SWAP_2_BYTES(uitem);
8549 }
8550 else {
8551 ushort= *(const GLushort *)uitem;
8552 }
8553
8554 assert(ushort <= 65535);
8555
8556 return (GLdouble)ushort;
8557 } /* extractUshort() */
8558
8559 static void shoveUshort(GLdouble value, int index, void *data)
8560 {
8561 assert(0.0 <= value && value < 65536.0);
8562
8563 ((GLushort *)data)[index]= (GLushort)value;
8564 } /* shoveUshort() */
8565
8566 static GLdouble extractSshort(int isSwap, const void *sitem)
8567 {
8568 GLshort sshort;
8569
8570 if (isSwap) {
8571 sshort= __GLU_SWAP_2_BYTES(sitem);
8572 }
8573 else {
8574 sshort= *(const GLshort *)sitem;
8575 }
8576
8577 assert(sshort <= 32767);
8578
8579 return (GLdouble)sshort;
8580 } /* extractSshort() */
8581
8582 static void shoveSshort(GLdouble value, int index, void *data)
8583 {
8584 assert(0.0 <= value && value < 32768.0);
8585
8586 ((GLshort *)data)[index]= (GLshort)value;
8587 } /* shoveSshort() */
8588
8589 static GLdouble extractUint(int isSwap, const void *uitem)
8590 {
8591 GLuint uint;
8592
8593 if (isSwap) {
8594 uint= __GLU_SWAP_4_BYTES(uitem);
8595 }
8596 else {
8597 uint= *(const GLuint *)uitem;
8598 }
8599
8600 assert(uint <= 0xffffffff);
8601
8602 return (GLdouble)uint;
8603 } /* extractUint() */
8604
8605 static void shoveUint(GLdouble value, int index, void *data)
8606 {
8607 assert(0.0 <= value && value <= (GLdouble) UINT_MAX);
8608
8609 ((GLuint *)data)[index]= (GLuint)value;
8610 } /* shoveUint() */
8611
8612 static GLdouble extractSint(int isSwap, const void *sitem)
8613 {
8614 GLint sint;
8615
8616 if (isSwap) {
8617 sint= __GLU_SWAP_4_BYTES(sitem);
8618 }
8619 else {
8620 sint= *(const GLint *)sitem;
8621 }
8622
8623 assert(sint <= 0x7fffffff);
8624
8625 return (GLdouble)sint;
8626 } /* extractSint() */
8627
8628 static void shoveSint(GLdouble value, int index, void *data)
8629 {
8630 assert(0.0 <= value && value <= (GLdouble) INT_MAX);
8631
8632 ((GLint *)data)[index]= (GLint)value;
8633 } /* shoveSint() */
8634
8635 static GLdouble extractFloat(int isSwap, const void *item)
8636 {
8637 GLfloat ffloat;
8638
8639 if (isSwap) {
8640 ffloat= __GLU_SWAP_4_BYTES(item);
8641 }
8642 else {
8643 ffloat= *(const GLfloat *)item;
8644 }
8645
8646 assert(ffloat <= 1.0);
8647
8648 return (GLdouble)ffloat;
8649 } /* extractFloat() */
8650
8651 static void shoveFloat(GLdouble value, int index, void *data)
8652 {
8653 assert(0.0 <= value && value <= 1.0);
8654
8655 ((GLfloat *)data)[index]= value;
8656 } /* shoveFloat() */
8657
8658 static void halveImageSlice(int components,
8659 GLdouble (*extract)(int, const void *),
8660 void (*shove)(GLdouble, int, void *),
8661 GLint width, GLint height, GLint depth,
8662 const void *dataIn, void *dataOut,
8663 GLint elementSizeInBytes,
8664 GLint groupSizeInBytes,
8665 GLint rowSizeInBytes,
8666 GLint imageSizeInBytes,
8667 GLint isSwap)
8668 {
8669 int ii, jj;
8670 int halfWidth= width / 2;
8671 int halfHeight= height / 2;
8672 int halfDepth= depth / 2;
8673 const char *src= (const char *)dataIn;
8674 int rowPadBytes= rowSizeInBytes - (width * groupSizeInBytes);
8675 int imagePadBytes= imageSizeInBytes - (width*height*groupSizeInBytes);
8676 int outIndex= 0;
8677
8678 assert((width == 1 || height == 1) && depth >= 2);
8679
8680 if (width == height) { /* a 1-pixel column viewed from top */
8681 /* printf("1-column\n");*/
8682 assert(width == 1 && height == 1);
8683 assert(depth >= 2);
8684
8685 for (ii= 0; ii< halfDepth; ii++) {
8686 int cc;
8687
8688 for (cc = 0; cc < components; cc++) {
8689 double totals[4];
8690 double extractTotals[BOX2][4];
8691 int kk;
8692
8693 extractTotals[0][cc]= (*extract)(isSwap,src);
8694 extractTotals[1][cc]= (*extract)(isSwap,(src+imageSizeInBytes));
8695
8696 /* average 2 pixels since only a column */
8697 totals[cc]= 0.0;
8698 /* totals[RED]= extractTotals[0][RED]+extractTotals[1][RED];
8699 * totals[RED]/= 2.0;
8700 */
8701 for (kk = 0; kk < BOX2; kk++) {
8702 totals[cc]+= extractTotals[kk][cc];
8703 }
8704 totals[cc]/= (double)BOX2;
8705
8706 (*shove)(totals[cc],outIndex,dataOut);
8707 outIndex++;
8708 src+= elementSizeInBytes;
8709 } /* for cc */
8710
8711 /* skip over to next group of 2 */
8712 src+= rowSizeInBytes;
8713 } /* for ii */
8714
8715 assert(src == &((const char *)dataIn)[rowSizeInBytes*height*depth]);
8716 assert(outIndex == halfDepth * components);
8717 }
8718 else if (height == 1) { /* horizontal slice viewed from top */
8719 /* printf("horizontal slice\n"); */
8720 assert(width != 1);
8721
8722 for (ii= 0; ii< halfDepth; ii++) {
8723 for (jj= 0; jj< halfWidth; jj++) {
8724 int cc;
8725
8726 for (cc = 0; cc < components; cc++) {
8727 int kk;
8728 double totals[4];
8729 double extractTotals[BOX4][4];
8730
8731 extractTotals[0][cc]=(*extract)(isSwap,src);
8732 extractTotals[1][cc]=(*extract)(isSwap,
8733 (src+groupSizeInBytes));
8734 extractTotals[2][cc]=(*extract)(isSwap,
8735 (src+imageSizeInBytes));
8736 extractTotals[3][cc]=(*extract)(isSwap,
8737 (src+imageSizeInBytes+groupSizeInBytes));
8738
8739 /* grab 4 pixels to average */
8740 totals[cc]= 0.0;
8741 /* totals[RED]= extractTotals[0][RED]+extractTotals[1][RED]+
8742 * extractTotals[2][RED]+extractTotals[3][RED];
8743 * totals[RED]/= 4.0;
8744 */
8745 for (kk = 0; kk < BOX4; kk++) {
8746 totals[cc]+= extractTotals[kk][cc];
8747 }
8748 totals[cc]/= (double)BOX4;
8749
8750 (*shove)(totals[cc],outIndex,dataOut);
8751 outIndex++;
8752
8753 src+= elementSizeInBytes;
8754 } /* for cc */
8755
8756 /* skip over to next horizontal square of 4 */
8757 src+= groupSizeInBytes;
8758 } /* for jj */
8759 src+= rowPadBytes;
8760
8761 src+= rowSizeInBytes;
8762 } /* for ii */
8763
8764 assert(src == &((const char *)dataIn)[rowSizeInBytes*height*depth]);
8765 assert(outIndex == halfWidth * halfDepth * components);
8766 }
8767 else if (width == 1) { /* vertical slice viewed from top */
8768 /* printf("vertical slice\n"); */
8769 assert(height != 1);
8770
8771 for (ii= 0; ii< halfDepth; ii++) {
8772 for (jj= 0; jj< halfHeight; jj++) {
8773 int cc;
8774
8775 for (cc = 0; cc < components; cc++) {
8776 int kk;
8777 double totals[4];
8778 double extractTotals[BOX4][4];
8779
8780 extractTotals[0][cc]=(*extract)(isSwap,src);
8781 extractTotals[1][cc]=(*extract)(isSwap,
8782 (src+rowSizeInBytes));
8783 extractTotals[2][cc]=(*extract)(isSwap,
8784 (src+imageSizeInBytes));
8785 extractTotals[3][cc]=(*extract)(isSwap,
8786 (src+imageSizeInBytes+rowSizeInBytes));
8787
8788 /* grab 4 pixels to average */
8789 totals[cc]= 0.0;
8790 /* totals[RED]= extractTotals[0][RED]+extractTotals[1][RED]+
8791 * extractTotals[2][RED]+extractTotals[3][RED];
8792 * totals[RED]/= 4.0;
8793 */
8794 for (kk = 0; kk < BOX4; kk++) {
8795 totals[cc]+= extractTotals[kk][cc];
8796 }
8797 totals[cc]/= (double)BOX4;
8798
8799 (*shove)(totals[cc],outIndex,dataOut);
8800 outIndex++;
8801
8802 src+= elementSizeInBytes;
8803 } /* for cc */
8804 src+= rowPadBytes;
8805
8806 /* skip over to next vertical square of 4 */
8807 src+= rowSizeInBytes;
8808 } /* for jj */
8809 src+= imagePadBytes;
8810
8811 src+= imageSizeInBytes;
8812 } /* for ii */
8813
8814 assert(src == &((const char *)dataIn)[rowSizeInBytes*height*depth]);
8815 assert(outIndex == halfHeight * halfDepth * components);
8816 }
8817
8818 } /* halveImageSlice() */
8819
8820 static void halveImage3D(int components,
8821 GLdouble (*extract)(int, const void *),
8822 void (*shove)(GLdouble, int, void *),
8823 GLint width, GLint height, GLint depth,
8824 const void *dataIn, void *dataOut,
8825 GLint elementSizeInBytes,
8826 GLint groupSizeInBytes,
8827 GLint rowSizeInBytes,
8828 GLint imageSizeInBytes,
8829 GLint isSwap)
8830 {
8831 assert(depth > 1);
8832
8833 /* a horizontal/vertical/one-column slice viewed from top */
8834 if (width == 1 || height == 1) {
8835 assert(1 <= depth);
8836
8837 halveImageSlice(components,extract,shove, width, height, depth,
8838 dataIn, dataOut, elementSizeInBytes, groupSizeInBytes,
8839 rowSizeInBytes, imageSizeInBytes, isSwap);
8840 return;
8841 }
8842 {
8843 int ii, jj, dd;
8844
8845 int halfWidth= width / 2;
8846 int halfHeight= height / 2;
8847 int halfDepth= depth / 2;
8848 const char *src= (const char *) dataIn;
8849 int rowPadBytes= rowSizeInBytes - (width*groupSizeInBytes);
8850 int imagePadBytes= imageSizeInBytes - (width*height*groupSizeInBytes);
8851 int outIndex= 0;
8852
8853 for (dd= 0; dd < halfDepth; dd++) {
8854 for (ii= 0; ii< halfHeight; ii++) {
8855 for (jj= 0; jj< halfWidth; jj++) {
8856 int cc;
8857
8858 for (cc= 0; cc < components; cc++) {
8859 int kk;
8860 #define BOX8 8
8861 double totals[4]; /* 4 is maximum components */
8862 double extractTotals[BOX8][4]; /* 4 is maximum components */
8863
8864 extractTotals[0][cc]= (*extract)(isSwap,src);
8865 extractTotals[1][cc]= (*extract)(isSwap,
8866 (src+groupSizeInBytes));
8867 extractTotals[2][cc]= (*extract)(isSwap,
8868 (src+rowSizeInBytes));
8869 extractTotals[3][cc]= (*extract)(isSwap,
8870 (src+rowSizeInBytes+groupSizeInBytes));
8871
8872 extractTotals[4][cc]= (*extract)(isSwap,
8873 (src+imageSizeInBytes));
8874
8875 extractTotals[5][cc]= (*extract)(isSwap,
8876 (src+groupSizeInBytes+imageSizeInBytes));
8877 extractTotals[6][cc]= (*extract)(isSwap,
8878 (src+rowSizeInBytes+imageSizeInBytes));
8879 extractTotals[7][cc]= (*extract)(isSwap,
8880 (src+rowSizeInBytes+groupSizeInBytes+imageSizeInBytes));
8881
8882 totals[cc]= 0.0;
8883
8884 /* totals[RED]= extractTotals[0][RED]+extractTotals[1][RED]+
8885 * extractTotals[2][RED]+extractTotals[3][RED]+
8886 * extractTotals[4][RED]+extractTotals[5][RED]+
8887 * extractTotals[6][RED]+extractTotals[7][RED];
8888 * totals[RED]/= 8.0;
8889 */
8890 for (kk = 0; kk < BOX8; kk++) {
8891 totals[cc]+= extractTotals[kk][cc];
8892 }
8893 totals[cc]/= (double)BOX8;
8894
8895 (*shove)(totals[cc],outIndex,dataOut);
8896
8897 outIndex++;
8898
8899 src+= elementSizeInBytes; /* go to next component */
8900 } /* for cc */
8901
8902 /* skip over to next square of 4 */
8903 src+= groupSizeInBytes;
8904 } /* for jj */
8905 /* skip past pad bytes, if any, to get to next row */
8906 src+= rowPadBytes;
8907
8908 /* src is at beginning of a row here, but it's the second row of
8909 * the square block of 4 pixels that we just worked on so we
8910 * need to go one more row.
8911 * i.e.,
8912 * OO...
8913 * here -->OO...
8914 * but want -->OO...
8915 * OO...
8916 * ...
8917 */
8918 src+= rowSizeInBytes;
8919 } /* for ii */
8920
8921 /* skip past pad bytes, if any, to get to next image */
8922 src+= imagePadBytes;
8923
8924 src+= imageSizeInBytes;
8925 } /* for dd */
8926
8927 /* both pointers must reach one byte after the end */
8928 assert(src == &((const char *)dataIn)[rowSizeInBytes*height*depth]);
8929 assert(outIndex == halfWidth * halfHeight * halfDepth * components);
8930 }
8931 } /* halveImage3D() */
8932
8933
8934
8935 /*** mipmap.c ***/
8936