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