3 * Mesa 3-D graphics library
5 * Copyright (C) 1995-2000 Brian Paul
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
17 * You should have received a copy of the GNU Library General Public
18 * License along with this library; if not, write to the Free
19 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
35 * Compute ceiling of integer quotient of A divided by B:
37 #define CEILING( A, B ) ( (A) % (B) == 0 ? (A)/(B) : (A)/(B)+1 )
47 /* To work around optimizer bug in MSVC4.1 */
48 #if defined(__WIN32__) && !defined(OPENSTEP)
50 dummy(GLuint j
, GLuint k
)
59 gluScaleImage(GLenum format
,
60 GLsizei widthin
, GLsizei heightin
,
61 GLenum typein
, const void *datain
,
62 GLsizei widthout
, GLsizei heightout
,
63 GLenum typeout
, void *dataout
)
65 GLint components
, i
, j
, k
;
66 GLfloat
*tempin
, *tempout
, f
;
68 GLint unpackrowlength
, unpackalignment
, unpackskiprows
, unpackskippixels
;
69 GLint packrowlength
, packalignment
, packskiprows
, packskippixels
;
70 GLint sizein
, sizeout
;
71 GLint rowstride
, rowlen
;
74 /* Determine number of components per pixel */
77 case GL_STENCIL_INDEX
:
78 case GL_DEPTH_COMPONENT
:
86 case GL_LUMINANCE_ALPHA
:
101 return GLU_INVALID_ENUM
;
104 /* Determine bytes per input datum */
106 case GL_UNSIGNED_BYTE
:
107 sizein
= sizeof(GLubyte
);
110 sizein
= sizeof(GLbyte
);
112 case GL_UNSIGNED_SHORT
:
113 sizein
= sizeof(GLushort
);
116 sizein
= sizeof(GLshort
);
118 case GL_UNSIGNED_INT
:
119 sizein
= sizeof(GLuint
);
122 sizein
= sizeof(GLint
);
125 sizein
= sizeof(GLfloat
);
128 /* not implemented yet */
130 return GL_INVALID_ENUM
;
133 /* Determine bytes per output datum */
135 case GL_UNSIGNED_BYTE
:
136 sizeout
= sizeof(GLubyte
);
139 sizeout
= sizeof(GLbyte
);
141 case GL_UNSIGNED_SHORT
:
142 sizeout
= sizeof(GLushort
);
145 sizeout
= sizeof(GLshort
);
147 case GL_UNSIGNED_INT
:
148 sizeout
= sizeof(GLuint
);
151 sizeout
= sizeof(GLint
);
154 sizeout
= sizeof(GLfloat
);
157 /* not implemented yet */
159 return GL_INVALID_ENUM
;
162 /* Get glPixelStore state */
163 glGetFloatv(GL_UNPACK_ROW_LENGTH
, &f
); unpackrowlength
= (int)f
;
164 glGetFloatv(GL_UNPACK_ALIGNMENT
, &f
); unpackalignment
= (int)f
;
165 glGetFloatv(GL_UNPACK_SKIP_ROWS
, &f
); unpackskiprows
= (int)f
;
166 glGetFloatv(GL_UNPACK_SKIP_PIXELS
, &f
); unpackskippixels
= (int)f
;
167 glGetFloatv(GL_PACK_ROW_LENGTH
, &f
); packrowlength
= (int)f
;
168 glGetFloatv(GL_PACK_ALIGNMENT
, &f
); packalignment
= (int)f
;
169 glGetFloatv(GL_PACK_SKIP_ROWS
, &f
); packskiprows
= (int)f
;
170 glGetFloatv(GL_PACK_SKIP_PIXELS
, &f
); packskippixels
= (int)f
;
172 /* Allocate storage for intermediate images */
173 tempin
= (GLfloat
*) malloc(widthin
* heightin
174 * components
* sizeof(GLfloat
));
176 return GLU_OUT_OF_MEMORY
;
178 tempout
= (GLfloat
*) malloc(widthout
* heightout
179 * components
* sizeof(GLfloat
));
182 return GLU_OUT_OF_MEMORY
;
187 * Unpack the pixel data and convert to floating point
190 if (unpackrowlength
> 0) {
191 rowlen
= unpackrowlength
;
196 if (sizein
>= unpackalignment
) {
197 rowstride
= components
* rowlen
;
200 rowstride
= unpackalignment
/ sizein
201 * CEILING(components
* rowlen
* sizein
, unpackalignment
);
205 case GL_UNSIGNED_BYTE
:
207 for (i
= 0; i
< heightin
; i
++) {
208 GLubyte
*ubptr
= (GLubyte
*) datain
210 + unpackskiprows
* rowstride
+ unpackskippixels
* components
;
211 for (j
= 0; j
< widthin
* components
; j
++) {
213 tempin
[k
++] = (GLfloat
) * ubptr
++;
219 for (i
= 0; i
< heightin
; i
++) {
220 GLbyte
*bptr
= (GLbyte
*) datain
222 + unpackskiprows
* rowstride
+ unpackskippixels
* components
;
223 for (j
= 0; j
< widthin
* components
; j
++) {
225 tempin
[k
++] = (GLfloat
) * bptr
++;
229 case GL_UNSIGNED_SHORT
:
231 for (i
= 0; i
< heightin
; i
++) {
232 GLushort
*usptr
= (GLushort
*) datain
234 + unpackskiprows
* rowstride
+ unpackskippixels
* components
;
235 for (j
= 0; j
< widthin
* components
; j
++) {
237 tempin
[k
++] = (GLfloat
) * usptr
++;
243 for (i
= 0; i
< heightin
; i
++) {
244 GLshort
*sptr
= (GLshort
*) datain
246 + unpackskiprows
* rowstride
+ unpackskippixels
* components
;
247 for (j
= 0; j
< widthin
* components
; j
++) {
249 tempin
[k
++] = (GLfloat
) * sptr
++;
253 case GL_UNSIGNED_INT
:
255 for (i
= 0; i
< heightin
; i
++) {
256 GLuint
*uiptr
= (GLuint
*) datain
258 + unpackskiprows
* rowstride
+ unpackskippixels
* components
;
259 for (j
= 0; j
< widthin
* components
; j
++) {
261 tempin
[k
++] = (GLfloat
) * uiptr
++;
267 for (i
= 0; i
< heightin
; i
++) {
268 GLint
*iptr
= (GLint
*) datain
270 + unpackskiprows
* rowstride
+ unpackskippixels
* components
;
271 for (j
= 0; j
< widthin
* components
; j
++) {
273 tempin
[k
++] = (GLfloat
) * iptr
++;
279 for (i
= 0; i
< heightin
; i
++) {
280 GLfloat
*fptr
= (GLfloat
*) datain
282 + unpackskiprows
* rowstride
+ unpackskippixels
* components
;
283 for (j
= 0; j
< widthin
* components
; j
++) {
285 tempin
[k
++] = *fptr
++;
290 return GLU_INVALID_ENUM
;
299 sx
= (GLfloat
) (widthin
- 1) / (GLfloat
) (widthout
- 1);
301 sx
= (GLfloat
) (widthin
- 1);
303 sy
= (GLfloat
) (heightin
- 1) / (GLfloat
) (heightout
- 1);
305 sy
= (GLfloat
) (heightin
- 1);
307 /*#define POINT_SAMPLE*/
309 for (i
= 0; i
< heightout
; i
++) {
311 for (j
= 0; j
< widthout
; j
++) {
314 GLfloat
*src
= tempin
+ (ii
* widthin
+ jj
) * components
;
315 GLfloat
*dst
= tempout
+ (i
* widthout
+ j
) * components
;
317 for (k
= 0; k
< components
; k
++) {
323 if (sx
< 1.0 && sy
< 1.0) {
324 /* magnify both width and height: use weighted sample of 4 pixels */
325 GLint i0
, i1
, j0
, j1
;
327 GLfloat
*src00
, *src01
, *src10
, *src11
;
331 for (i
= 0; i
< heightout
; i
++) {
336 /* i1 = (i+1) * sy - EPSILON;*/
338 for (j
= 0; j
< widthout
; j
++) {
343 /* j1 = (j+1) * sx - EPSILON; */
346 /* compute weighted average of pixels in rect (i0,j0)-(i1,j1) */
347 src00
= tempin
+ (i0
* widthin
+ j0
) * components
;
348 src01
= tempin
+ (i0
* widthin
+ j1
) * components
;
349 src10
= tempin
+ (i1
* widthin
+ j0
) * components
;
350 src11
= tempin
+ (i1
* widthin
+ j1
) * components
;
352 dst
= tempout
+ (i
* widthout
+ j
) * components
;
354 for (k
= 0; k
< components
; k
++) {
355 s1
= *src00
++ * (1.0 - beta
) + *src01
++ * beta
;
356 s2
= *src10
++ * (1.0 - beta
) + *src11
++ * beta
;
357 *dst
++ = s1
* (1.0 - alpha
) + s2
* alpha
;
363 /* shrink width and/or height: use an unweighted box filter */
369 for (i
= 0; i
< heightout
; i
++) {
374 /* i1 = (i+1) * sy - EPSILON; */
375 for (j
= 0; j
< widthout
; j
++) {
380 /* j1 = (j+1) * sx - EPSILON; */
382 dst
= tempout
+ (i
* widthout
+ j
) * components
;
384 /* compute average of pixels in the rectangle (i0,j0)-(i1,j1) */
385 for (k
= 0; k
< components
; k
++) {
387 for (ii
= i0
; ii
<= i1
; ii
++) {
388 for (jj
= j0
; jj
<= j1
; jj
++) {
389 sum
+= *(tempin
+ (ii
* widthin
+ jj
) * components
+ k
);
392 sum
/= (j1
- j0
+ 1) * (i1
- i0
+ 1);
402 * Return output image
405 if (packrowlength
> 0) {
406 rowlen
= packrowlength
;
411 if (sizeout
>= packalignment
) {
412 rowstride
= components
* rowlen
;
415 rowstride
= packalignment
/ sizeout
416 * CEILING(components
* rowlen
* sizeout
, packalignment
);
420 case GL_UNSIGNED_BYTE
:
422 for (i
= 0; i
< heightout
; i
++) {
423 GLubyte
*ubptr
= (GLubyte
*) dataout
425 + packskiprows
* rowstride
+ packskippixels
* components
;
426 for (j
= 0; j
< widthout
* components
; j
++) {
428 *ubptr
++ = (GLubyte
) tempout
[k
++];
434 for (i
= 0; i
< heightout
; i
++) {
435 GLbyte
*bptr
= (GLbyte
*) dataout
437 + packskiprows
* rowstride
+ packskippixels
* components
;
438 for (j
= 0; j
< widthout
* components
; j
++) {
440 *bptr
++ = (GLbyte
) tempout
[k
++];
444 case GL_UNSIGNED_SHORT
:
446 for (i
= 0; i
< heightout
; i
++) {
447 GLushort
*usptr
= (GLushort
*) dataout
449 + packskiprows
* rowstride
+ packskippixels
* components
;
450 for (j
= 0; j
< widthout
* components
; j
++) {
452 *usptr
++ = (GLushort
) tempout
[k
++];
458 for (i
= 0; i
< heightout
; i
++) {
459 GLshort
*sptr
= (GLshort
*) dataout
461 + packskiprows
* rowstride
+ packskippixels
* components
;
462 for (j
= 0; j
< widthout
* components
; j
++) {
464 *sptr
++ = (GLshort
) tempout
[k
++];
468 case GL_UNSIGNED_INT
:
470 for (i
= 0; i
< heightout
; i
++) {
471 GLuint
*uiptr
= (GLuint
*) dataout
473 + packskiprows
* rowstride
+ packskippixels
* components
;
474 for (j
= 0; j
< widthout
* components
; j
++) {
476 *uiptr
++ = (GLuint
) tempout
[k
++];
482 for (i
= 0; i
< heightout
; i
++) {
483 GLint
*iptr
= (GLint
*) dataout
485 + packskiprows
* rowstride
+ packskippixels
* components
;
486 for (j
= 0; j
< widthout
* components
; j
++) {
488 *iptr
++ = (GLint
) tempout
[k
++];
494 for (i
= 0; i
< heightout
; i
++) {
495 GLfloat
*fptr
= (GLfloat
*) dataout
497 + packskiprows
* rowstride
+ packskippixels
* components
;
498 for (j
= 0; j
< widthout
* components
; j
++) {
500 *fptr
++ = tempout
[k
++];
505 return GLU_INVALID_ENUM
;
509 /* free temporary image storage */
519 * Return the largest k such that 2^k <= n.
528 for (k
= 0; n
>>= 1; k
++);
535 * Find the value nearest to n which is also a power of two.
542 for (m
= 1; m
< n
; m
*= 2);
545 if (m
- n
<= n
- m
/ 2) {
555 * Given an pixel format and data type, return the number of bytes to
559 bytes_per_pixel(GLenum format
, GLenum type
)
565 case GL_STENCIL_INDEX
:
566 case GL_DEPTH_COMPONENT
:
574 case GL_LUMINANCE_ALPHA
:
593 case GL_UNSIGNED_BYTE
:
602 case GL_UNSIGNED_SHORT
:
603 m
= sizeof(GLushort
);
608 case GL_UNSIGNED_INT
:
627 * WARNING: This function isn't finished and has never been tested!!!!
630 gluBuild1DMipmaps(GLenum target
, GLint components
,
631 GLsizei width
, GLenum format
, GLenum type
, const void *data
)
639 gluBuild2DMipmaps(GLenum target
, GLint components
,
640 GLsizei width
, GLsizei height
, GLenum format
,
641 GLenum type
, const void *data
)
645 void *image
, *newimage
;
646 GLint neww
, newh
, level
, bpp
;
650 GLint unpackrowlength
, unpackalignment
, unpackskiprows
, unpackskippixels
;
651 GLint packrowlength
, packalignment
, packskiprows
, packskippixels
;
654 if (width
< 1 || height
< 1)
655 return GLU_INVALID_VALUE
;
657 glGetFloatv(GL_MAX_TEXTURE_SIZE
, &f
); maxsize
= (int)f
;
668 bpp
= bytes_per_pixel(format
, type
);
670 /* probably a bad format or type enum */
671 return GLU_INVALID_ENUM
;
674 /* Get current glPixelStore values */
675 glGetFloatv(GL_UNPACK_ROW_LENGTH
, &f
); unpackrowlength
= (int)f
;
676 glGetFloatv(GL_UNPACK_ALIGNMENT
, &f
); unpackalignment
= (int)f
;
677 glGetFloatv(GL_UNPACK_SKIP_ROWS
, &f
); unpackskiprows
= (int)f
;
678 glGetFloatv(GL_UNPACK_SKIP_PIXELS
, &f
); unpackskippixels
= (int)f
;
679 glGetFloatv(GL_PACK_ROW_LENGTH
, &f
); packrowlength
= (int)f
;
680 glGetFloatv(GL_PACK_ALIGNMENT
, &f
); packalignment
= (int)f
;
681 glGetFloatv(GL_PACK_SKIP_ROWS
, &f
); packskiprows
= (int)f
;
682 glGetFloatv(GL_PACK_SKIP_PIXELS
, &f
); packskippixels
= (int)f
;
684 /* set pixel packing */
685 glPixelStorei(GL_PACK_ROW_LENGTH
, 0);
686 glPixelStorei(GL_PACK_ALIGNMENT
, 1);
687 glPixelStorei(GL_PACK_SKIP_ROWS
, 0);
688 glPixelStorei(GL_PACK_SKIP_PIXELS
, 0);
692 if (w
!= width
|| h
!= height
) {
693 /* must rescale image to get "top" mipmap texture image */
694 image
= malloc((w
+ 4) * h
* bpp
);
696 return GLU_OUT_OF_MEMORY
;
698 error
= gluScaleImage(format
, width
, height
, type
, data
,
706 image
= (void *) data
;
712 /* set pixel unpacking */
713 glPixelStorei(GL_UNPACK_ROW_LENGTH
, 0);
714 glPixelStorei(GL_UNPACK_ALIGNMENT
, 1);
715 glPixelStorei(GL_UNPACK_SKIP_ROWS
, 0);
716 glPixelStorei(GL_UNPACK_SKIP_PIXELS
, 0);
719 glTexImage2D(target
, level
, components
, w
, h
, 0, format
, type
, image
);
721 if (w
== 1 && h
== 1)
724 neww
= (w
< 2) ? 1 : w
/ 2;
725 newh
= (h
< 2) ? 1 : h
/ 2;
726 newimage
= malloc((neww
+ 4) * newh
* bpp
);
728 return GLU_OUT_OF_MEMORY
;
731 error
= gluScaleImage(format
, w
, h
, type
, image
,
732 neww
, newh
, type
, newimage
);
752 /* Restore original glPixelStore state */
753 glPixelStorei(GL_UNPACK_ROW_LENGTH
, unpackrowlength
);
754 glPixelStorei(GL_UNPACK_ALIGNMENT
, unpackalignment
);
755 glPixelStorei(GL_UNPACK_SKIP_ROWS
, unpackskiprows
);
756 glPixelStorei(GL_UNPACK_SKIP_PIXELS
, unpackskippixels
);
757 glPixelStorei(GL_PACK_ROW_LENGTH
, packrowlength
);
758 glPixelStorei(GL_PACK_ALIGNMENT
, packalignment
);
759 glPixelStorei(GL_PACK_SKIP_ROWS
, packskiprows
);
760 glPixelStorei(GL_PACK_SKIP_PIXELS
, packskippixels
);