ad6b6e63a62e2daad0888ddea7f1b0342726a363
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
;
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 glGetIntegerv(GL_UNPACK_ROW_LENGTH
, &unpackrowlength
);
164 glGetIntegerv(GL_UNPACK_ALIGNMENT
, &unpackalignment
);
165 glGetIntegerv(GL_UNPACK_SKIP_ROWS
, &unpackskiprows
);
166 glGetIntegerv(GL_UNPACK_SKIP_PIXELS
, &unpackskippixels
);
167 glGetIntegerv(GL_PACK_ROW_LENGTH
, &packrowlength
);
168 glGetIntegerv(GL_PACK_ALIGNMENT
, &packalignment
);
169 glGetIntegerv(GL_PACK_SKIP_ROWS
, &packskiprows
);
170 glGetIntegerv(GL_PACK_SKIP_PIXELS
, &packskippixels
);
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
++;
293 return GLU_INVALID_ENUM
;
303 sx
= (GLfloat
) (widthin
- 1) / (GLfloat
) (widthout
- 1);
305 sx
= (GLfloat
) (widthin
- 1);
307 sy
= (GLfloat
) (heightin
- 1) / (GLfloat
) (heightout
- 1);
309 sy
= (GLfloat
) (heightin
- 1);
311 /*#define POINT_SAMPLE*/
313 for (i
= 0; i
< heightout
; i
++) {
315 for (j
= 0; j
< widthout
; j
++) {
318 GLfloat
*src
= tempin
+ (ii
* widthin
+ jj
) * components
;
319 GLfloat
*dst
= tempout
+ (i
* widthout
+ j
) * components
;
321 for (k
= 0; k
< components
; k
++) {
327 if (sx
< 1.0 && sy
< 1.0) {
328 /* magnify both width and height: use weighted sample of 4 pixels */
329 GLint i0
, i1
, j0
, j1
;
331 GLfloat
*src00
, *src01
, *src10
, *src11
;
335 for (i
= 0; i
< heightout
; i
++) {
340 /* i1 = (i+1) * sy - EPSILON;*/
342 for (j
= 0; j
< widthout
; j
++) {
347 /* j1 = (j+1) * sx - EPSILON; */
350 /* compute weighted average of pixels in rect (i0,j0)-(i1,j1) */
351 src00
= tempin
+ (i0
* widthin
+ j0
) * components
;
352 src01
= tempin
+ (i0
* widthin
+ j1
) * components
;
353 src10
= tempin
+ (i1
* widthin
+ j0
) * components
;
354 src11
= tempin
+ (i1
* widthin
+ j1
) * components
;
356 dst
= tempout
+ (i
* widthout
+ j
) * components
;
358 for (k
= 0; k
< components
; k
++) {
359 s1
= *src00
++ * (1.0 - beta
) + *src01
++ * beta
;
360 s2
= *src10
++ * (1.0 - beta
) + *src11
++ * beta
;
361 *dst
++ = s1
* (1.0 - alpha
) + s2
* alpha
;
367 /* shrink width and/or height: use an unweighted box filter */
373 for (i
= 0; i
< heightout
; i
++) {
378 /* i1 = (i+1) * sy - EPSILON; */
379 for (j
= 0; j
< widthout
; j
++) {
384 /* j1 = (j+1) * sx - EPSILON; */
386 dst
= tempout
+ (i
* widthout
+ j
) * components
;
388 /* compute average of pixels in the rectangle (i0,j0)-(i1,j1) */
389 for (k
= 0; k
< components
; k
++) {
391 for (ii
= i0
; ii
<= i1
; ii
++) {
392 for (jj
= j0
; jj
<= j1
; jj
++) {
393 sum
+= *(tempin
+ (ii
* widthin
+ jj
) * components
+ k
);
396 sum
/= (j1
- j0
+ 1) * (i1
- i0
+ 1);
406 * Return output image
409 if (packrowlength
> 0) {
410 rowlen
= packrowlength
;
415 if (sizeout
>= packalignment
) {
416 rowstride
= components
* rowlen
;
419 rowstride
= packalignment
/ sizeout
420 * CEILING(components
* rowlen
* sizeout
, packalignment
);
424 case GL_UNSIGNED_BYTE
:
426 for (i
= 0; i
< heightout
; i
++) {
427 GLubyte
*ubptr
= (GLubyte
*) dataout
429 + packskiprows
* rowstride
+ packskippixels
* components
;
430 for (j
= 0; j
< widthout
* components
; j
++) {
432 *ubptr
++ = (GLubyte
) tempout
[k
++];
438 for (i
= 0; i
< heightout
; i
++) {
439 GLbyte
*bptr
= (GLbyte
*) dataout
441 + packskiprows
* rowstride
+ packskippixels
* components
;
442 for (j
= 0; j
< widthout
* components
; j
++) {
444 *bptr
++ = (GLbyte
) tempout
[k
++];
448 case GL_UNSIGNED_SHORT
:
450 for (i
= 0; i
< heightout
; i
++) {
451 GLushort
*usptr
= (GLushort
*) dataout
453 + packskiprows
* rowstride
+ packskippixels
* components
;
454 for (j
= 0; j
< widthout
* components
; j
++) {
456 *usptr
++ = (GLushort
) tempout
[k
++];
462 for (i
= 0; i
< heightout
; i
++) {
463 GLshort
*sptr
= (GLshort
*) dataout
465 + packskiprows
* rowstride
+ packskippixels
* components
;
466 for (j
= 0; j
< widthout
* components
; j
++) {
468 *sptr
++ = (GLshort
) tempout
[k
++];
472 case GL_UNSIGNED_INT
:
474 for (i
= 0; i
< heightout
; i
++) {
475 GLuint
*uiptr
= (GLuint
*) dataout
477 + packskiprows
* rowstride
+ packskippixels
* components
;
478 for (j
= 0; j
< widthout
* components
; j
++) {
480 *uiptr
++ = (GLuint
) tempout
[k
++];
486 for (i
= 0; i
< heightout
; i
++) {
487 GLint
*iptr
= (GLint
*) dataout
489 + packskiprows
* rowstride
+ packskippixels
* components
;
490 for (j
= 0; j
< widthout
* components
; j
++) {
492 *iptr
++ = (GLint
) tempout
[k
++];
498 for (i
= 0; i
< heightout
; i
++) {
499 GLfloat
*fptr
= (GLfloat
*) dataout
501 + packskiprows
* rowstride
+ packskippixels
* components
;
502 for (j
= 0; j
< widthout
* components
; j
++) {
504 *fptr
++ = tempout
[k
++];
509 return GLU_INVALID_ENUM
;
513 /* free temporary image storage */
523 * Return the largest k such that 2^k <= n.
532 for (k
= 0; n
>>= 1; k
++);
539 * Find the value nearest to n which is also a power of two.
546 for (m
= 1; m
< n
; m
*= 2);
549 if (m
- n
<= n
- m
/ 2) {
559 * Given an pixel format and datatype, return the number of bytes to
563 bytes_per_pixel(GLenum format
, GLenum type
)
569 case GL_STENCIL_INDEX
:
570 case GL_DEPTH_COMPONENT
:
578 case GL_LUMINANCE_ALPHA
:
597 case GL_UNSIGNED_BYTE
:
606 case GL_UNSIGNED_SHORT
:
607 m
= sizeof(GLushort
);
612 case GL_UNSIGNED_INT
:
631 * WARNING: This function isn't finished and has never been tested!!!!
634 gluBuild1DMipmaps(GLenum target
, GLint components
,
635 GLsizei width
, GLenum format
, GLenum type
, const void *data
)
638 GLint levels
, max_levels
;
639 GLint new_width
, max_width
;
643 return GLU_INVALID_VALUE
;
645 glGetIntegerv(GL_MAX_TEXTURE_SIZE
, &max_width
);
646 max_levels
= ilog2(max_width
) + 1;
648 /* Compute how many mipmap images to make */
649 levels
= ilog2(width
) + 1;
650 if (levels
> max_levels
) {
654 new_width
= 1 << (levels
- 1);
656 texture
= (GLubyte
*) malloc(new_width
* components
);
658 return GLU_OUT_OF_MEMORY
;
661 if (width
!= new_width
) {
662 /* initial rescaling */
664 case GL_UNSIGNED_BYTE
:
666 GLubyte
*ub_data
= (GLubyte
*) data
;
667 for (i
= 0; i
< new_width
; i
++) {
668 j
= i
* width
/ new_width
;
669 for (k
= 0; k
< components
; k
++) {
670 texture
[i
* components
+ k
] = ub_data
[j
* components
+ k
];
676 /* Not implemented */
682 /* generate and load mipmap images */
683 for (l
= 0; l
< levels
; l
++) {
684 glTexImage1D(GL_TEXTURE_1D
, l
, components
, new_width
, 0,
685 format
, GL_UNSIGNED_BYTE
, texture
);
687 /* Scale image down to 1/2 size */
688 new_width
= new_width
/ 2;
689 for (i
= 0; i
< new_width
; i
++) {
690 for (k
= 0; k
< components
; k
++) {
691 GLint sample1
, sample2
;
692 sample1
= (GLint
) texture
[i
* 2 * components
+ k
];
693 sample2
= (GLint
) texture
[(i
* 2 + 1) * components
+ k
];
694 texture
[i
* components
+ k
] = (GLubyte
) ((sample1
+ sample2
) / 2);
707 gluBuild2DMipmaps(GLenum target
, GLint components
,
708 GLsizei width
, GLsizei height
, GLenum format
,
709 GLenum type
, const void *data
)
712 void *image
, *newimage
;
713 GLint neww
, newh
, level
, bpp
;
717 GLint unpackrowlength
, unpackalignment
, unpackskiprows
, unpackskippixels
;
718 GLint packrowlength
, packalignment
, packskiprows
, packskippixels
;
720 if (width
< 1 || height
< 1)
721 return GLU_INVALID_VALUE
;
723 glGetIntegerv(GL_MAX_TEXTURE_SIZE
, &maxsize
);
734 bpp
= bytes_per_pixel(format
, type
);
736 /* probably a bad format or type enum */
737 return GLU_INVALID_ENUM
;
740 /* Get current glPixelStore values */
741 glGetIntegerv(GL_UNPACK_ROW_LENGTH
, &unpackrowlength
);
742 glGetIntegerv(GL_UNPACK_ALIGNMENT
, &unpackalignment
);
743 glGetIntegerv(GL_UNPACK_SKIP_ROWS
, &unpackskiprows
);
744 glGetIntegerv(GL_UNPACK_SKIP_PIXELS
, &unpackskippixels
);
745 glGetIntegerv(GL_PACK_ROW_LENGTH
, &packrowlength
);
746 glGetIntegerv(GL_PACK_ALIGNMENT
, &packalignment
);
747 glGetIntegerv(GL_PACK_SKIP_ROWS
, &packskiprows
);
748 glGetIntegerv(GL_PACK_SKIP_PIXELS
, &packskippixels
);
750 /* set pixel packing */
751 glPixelStorei(GL_PACK_ROW_LENGTH
, 0);
752 glPixelStorei(GL_PACK_ALIGNMENT
, 1);
753 glPixelStorei(GL_PACK_SKIP_ROWS
, 0);
754 glPixelStorei(GL_PACK_SKIP_PIXELS
, 0);
758 if (w
!= width
|| h
!= height
) {
759 /* must rescale image to get "top" mipmap texture image */
760 image
= malloc((w
+ 4) * h
* bpp
);
762 return GLU_OUT_OF_MEMORY
;
764 error
= gluScaleImage(format
, width
, height
, type
, data
,
772 image
= (void *) data
;
778 /* set pixel unpacking */
779 glPixelStorei(GL_UNPACK_ROW_LENGTH
, 0);
780 glPixelStorei(GL_UNPACK_ALIGNMENT
, 1);
781 glPixelStorei(GL_UNPACK_SKIP_ROWS
, 0);
782 glPixelStorei(GL_UNPACK_SKIP_PIXELS
, 0);
785 glTexImage2D(target
, level
, components
, w
, h
, 0, format
, type
, image
);
787 if (w
== 1 && h
== 1)
790 neww
= (w
< 2) ? 1 : w
/ 2;
791 newh
= (h
< 2) ? 1 : h
/ 2;
792 newimage
= malloc((neww
+ 4) * newh
* bpp
);
794 return GLU_OUT_OF_MEMORY
;
797 error
= gluScaleImage(format
, w
, h
, type
, image
,
798 neww
, newh
, type
, newimage
);
818 /* Restore original glPixelStore state */
819 glPixelStorei(GL_UNPACK_ROW_LENGTH
, unpackrowlength
);
820 glPixelStorei(GL_UNPACK_ALIGNMENT
, unpackalignment
);
821 glPixelStorei(GL_UNPACK_SKIP_ROWS
, unpackskiprows
);
822 glPixelStorei(GL_UNPACK_SKIP_PIXELS
, unpackskippixels
);
823 glPixelStorei(GL_PACK_ROW_LENGTH
, packrowlength
);
824 glPixelStorei(GL_PACK_ALIGNMENT
, packalignment
);
825 glPixelStorei(GL_PACK_SKIP_ROWS
, packskiprows
);
826 glPixelStorei(GL_PACK_SKIP_PIXELS
, packskippixels
);