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