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++;
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 datatype, 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)
634
GLint levels, max_levels;
635
GLint new_width, max_width;
639
return GLU_INVALID_VALUE;
641
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_width);
642
max_levels = ilog2(max_width) + 1;
644
/* Compute how many mipmap images to make */
645
levels = ilog2(width) + 1;
646
if (levels > max_levels) {
650
new_width = 1 << (levels - 1);
652
texture = (GLubyte *) malloc(new_width * components);
654
return GLU_OUT_OF_MEMORY;
657
if (width != new_width) {
658
/* initial rescaling */
660
case GL_UNSIGNED_BYTE:
662
GLubyte *ub_data = (GLubyte *) data;
663
for (i = 0; i < new_width; i++) {
664
j = i * width / new_width;
665
for (k = 0; k < components; k++) {
666
texture[i * components + k] = ub_data[j * components + k];
672
/* Not implemented */
677
/* generate and load mipmap images */
678
for (l = 0; l < levels; l++) {
679
glTexImage1D(GL_TEXTURE_1D, l, components, new_width, 0,
680
format, GL_UNSIGNED_BYTE, texture);
682
/* Scale image down to 1/2 size */
683
new_width = new_width / 2;
684
for (i = 0; i < new_width; i++) {
685
for (k = 0; k < components; k++) {
686
GLint sample1, sample2;
687
sample1 = (GLint) texture[i * 2 * components + k];
688
sample2 = (GLint) texture[(i * 2 + 1) * components + k];
689
texture[i * components + k] = (GLubyte) ((sample1 + sample2) / 2);
702
gluBuild2DMipmaps(GLenum target, GLint components,
703
GLsizei width, GLsizei height, GLenum format,
704
GLenum type, const void *data)
707
void *image, *newimage;
708
GLint neww, newh, level, bpp;
712
GLint unpackrowlength, unpackalignment, unpackskiprows, unpackskippixels;
713
GLint packrowlength, packalignment, packskiprows, packskippixels;
715
if (width < 1 || height < 1)
716
return GLU_INVALID_VALUE;
718
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxsize);
729
bpp = bytes_per_pixel(format, type);
731
/* probably a bad format or type enum */
732
return GLU_INVALID_ENUM;
735
/* Get current glPixelStore values */
736
glGetIntegerv(GL_UNPACK_ROW_LENGTH, &unpackrowlength);
737
glGetIntegerv(GL_UNPACK_ALIGNMENT, &unpackalignment);
738
glGetIntegerv(GL_UNPACK_SKIP_ROWS, &unpackskiprows);
739
glGetIntegerv(GL_UNPACK_SKIP_PIXELS, &unpackskippixels);
740
glGetIntegerv(GL_PACK_ROW_LENGTH, &packrowlength);
741
glGetIntegerv(GL_PACK_ALIGNMENT, &packalignment);
742
glGetIntegerv(GL_PACK_SKIP_ROWS, &packskiprows);
743
glGetIntegerv(GL_PACK_SKIP_PIXELS, &packskippixels);
745
/* set pixel packing */
746
glPixelStorei(GL_PACK_ROW_LENGTH, 0);
747
glPixelStorei(GL_PACK_ALIGNMENT, 1);
748
glPixelStorei(GL_PACK_SKIP_ROWS, 0);
749
glPixelStorei(GL_PACK_SKIP_PIXELS, 0);
753
if (w != width || h != height) {
754
/* must rescale image to get "top" mipmap texture image */
755
image = malloc((w + 4) * h * bpp);
757
return GLU_OUT_OF_MEMORY;
759
error = gluScaleImage(format, width, height, type, data,
767
image = (void *) data;
773
/* set pixel unpacking */
774
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
775
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
776
glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
777
glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
780
glTexImage2D(target, level, components, w, h, 0, format, type, image);
782
if (w == 1 && h == 1)
785
neww = (w < 2) ? 1 : w / 2;
786
newh = (h < 2) ? 1 : h / 2;
787
newimage = malloc((neww + 4) * newh * bpp);
789
return GLU_OUT_OF_MEMORY;
792
error = gluScaleImage(format, w, h, type, image,
793
neww, newh, type, newimage);
813
/* Restore original glPixelStore state */
814
glPixelStorei(GL_UNPACK_ROW_LENGTH, unpackrowlength);
815
glPixelStorei(GL_UNPACK_ALIGNMENT, unpackalignment);
816
glPixelStorei(GL_UNPACK_SKIP_ROWS, unpackskiprows);
817
glPixelStorei(GL_UNPACK_SKIP_PIXELS, unpackskippixels);
818
glPixelStorei(GL_PACK_ROW_LENGTH, packrowlength);
819
glPixelStorei(GL_PACK_ALIGNMENT, packalignment);
820
glPixelStorei(GL_PACK_SKIP_ROWS, packskiprows);
821
glPixelStorei(GL_PACK_SKIP_PIXELS, packskippixels);