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