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