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