~ubuntu-branches/ubuntu/quantal/mesa/quantal

« back to all changes in this revision

Viewing changes to src/glu/mesa/mipmap.c

  • Committer: Bazaar Package Importer
  • Author(s): Sebastien Bacher
  • Date: 2007-02-21 12:44:07 UTC
  • mfrom: (1.2.1 upstream)
  • mto: This revision was merged to the branch mainline in revision 22.
  • Revision ID: james.westby@ubuntu.com-20070221124407-rgcacs32mycrtadl
ImportĀ upstreamĀ versionĀ 6.5.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
 
2
 
/*
3
 
 * Mesa 3-D graphics library
4
 
 * Version:  3.4
5
 
 * Copyright (C) 1995-2000  Brian Paul
6
 
 *
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.
11
 
 *
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.
16
 
 *
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.
20
 
 */
21
 
 
22
 
 
23
 
#ifdef PC_HEADER
24
 
#include "all.h"
25
 
#else
26
 
#include <assert.h>
27
 
#include <math.h>
28
 
#include <stdio.h>
29
 
#include <stdlib.h>
30
 
#include "gluP.h"
31
 
#endif
32
 
 
33
 
 
34
 
/*
35
 
 * Compute ceiling of integer quotient of A divided by B:
36
 
 */
37
 
#define CEILING( A, B )  ( (A) % (B) == 0 ? (A)/(B) : (A)/(B)+1 )
38
 
 
39
 
 
40
 
 
41
 
#ifdef EPSILON
42
 
#undef EPSILON
43
 
#endif
44
 
#define EPSILON 0.001
45
 
 
46
 
 
47
 
/* To work around optimizer bug in MSVC4.1 */
48
 
#if defined(__WIN32__) && !defined(OPENSTEP)
49
 
void
50
 
dummy(GLuint j, GLuint k)
51
 
{
52
 
}
53
 
#else
54
 
#define dummy(J, K)
55
 
#endif
56
 
 
57
 
 
58
 
GLint GLAPIENTRY
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)
64
 
{
65
 
   GLint components, i, j, k;
66
 
   GLfloat *tempin, *tempout;
67
 
   GLfloat sx, sy;
68
 
   GLint unpackrowlength, unpackalignment, unpackskiprows, unpackskippixels;
69
 
   GLint packrowlength, packalignment, packskiprows, packskippixels;
70
 
   GLint sizein, sizeout;
71
 
   GLint rowstride, rowlen;
72
 
 
73
 
 
74
 
   /* Determine number of components per pixel */
75
 
   switch (format) {
76
 
   case GL_COLOR_INDEX:
77
 
   case GL_STENCIL_INDEX:
78
 
   case GL_DEPTH_COMPONENT:
79
 
   case GL_RED:
80
 
   case GL_GREEN:
81
 
   case GL_BLUE:
82
 
   case GL_ALPHA:
83
 
   case GL_LUMINANCE:
84
 
      components = 1;
85
 
      break;
86
 
   case GL_LUMINANCE_ALPHA:
87
 
      components = 2;
88
 
      break;
89
 
   case GL_RGB:
90
 
   case GL_BGR:
91
 
      components = 3;
92
 
      break;
93
 
   case GL_RGBA:
94
 
   case GL_BGRA:
95
 
#ifdef GL_EXT_abgr
96
 
   case GL_ABGR_EXT:
97
 
#endif
98
 
      components = 4;
99
 
      break;
100
 
   default:
101
 
      return GLU_INVALID_ENUM;
102
 
   }
103
 
 
104
 
   /* Determine bytes per input datum */
105
 
   switch (typein) {
106
 
   case GL_UNSIGNED_BYTE:
107
 
      sizein = sizeof(GLubyte);
108
 
      break;
109
 
   case GL_BYTE:
110
 
      sizein = sizeof(GLbyte);
111
 
      break;
112
 
   case GL_UNSIGNED_SHORT:
113
 
      sizein = sizeof(GLushort);
114
 
      break;
115
 
   case GL_SHORT:
116
 
      sizein = sizeof(GLshort);
117
 
      break;
118
 
   case GL_UNSIGNED_INT:
119
 
      sizein = sizeof(GLuint);
120
 
      break;
121
 
   case GL_INT:
122
 
      sizein = sizeof(GLint);
123
 
      break;
124
 
   case GL_FLOAT:
125
 
      sizein = sizeof(GLfloat);
126
 
      break;
127
 
   case GL_BITMAP:
128
 
      /* not implemented yet */
129
 
   default:
130
 
      return GL_INVALID_ENUM;
131
 
   }
132
 
 
133
 
   /* Determine bytes per output datum */
134
 
   switch (typeout) {
135
 
   case GL_UNSIGNED_BYTE:
136
 
      sizeout = sizeof(GLubyte);
137
 
      break;
138
 
   case GL_BYTE:
139
 
      sizeout = sizeof(GLbyte);
140
 
      break;
141
 
   case GL_UNSIGNED_SHORT:
142
 
      sizeout = sizeof(GLushort);
143
 
      break;
144
 
   case GL_SHORT:
145
 
      sizeout = sizeof(GLshort);
146
 
      break;
147
 
   case GL_UNSIGNED_INT:
148
 
      sizeout = sizeof(GLuint);
149
 
      break;
150
 
   case GL_INT:
151
 
      sizeout = sizeof(GLint);
152
 
      break;
153
 
   case GL_FLOAT:
154
 
      sizeout = sizeof(GLfloat);
155
 
      break;
156
 
   case GL_BITMAP:
157
 
      /* not implemented yet */
158
 
   default:
159
 
      return GL_INVALID_ENUM;
160
 
   }
161
 
 
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);
171
 
 
172
 
   /* Allocate storage for intermediate images */
173
 
   tempin = (GLfloat *) malloc(widthin * heightin
174
 
                               * components * sizeof(GLfloat));
175
 
   if (!tempin) {
176
 
      return GLU_OUT_OF_MEMORY;
177
 
   }
178
 
   tempout = (GLfloat *) malloc(widthout * heightout
179
 
                                * components * sizeof(GLfloat));
180
 
   if (!tempout) {
181
 
      free(tempin);
182
 
      return GLU_OUT_OF_MEMORY;
183
 
   }
184
 
 
185
 
 
186
 
   /*
187
 
    * Unpack the pixel data and convert to floating point
188
 
    */
189
 
 
190
 
   if (unpackrowlength > 0) {
191
 
      rowlen = unpackrowlength;
192
 
   }
193
 
   else {
194
 
      rowlen = widthin;
195
 
   }
196
 
   if (sizein >= unpackalignment) {
197
 
      rowstride = components * rowlen;
198
 
   }
199
 
   else {
200
 
      rowstride = unpackalignment / sizein
201
 
         * CEILING(components * rowlen * sizein, unpackalignment);
202
 
   }
203
 
 
204
 
   switch (typein) {
205
 
   case GL_UNSIGNED_BYTE:
206
 
      k = 0;
207
 
      for (i = 0; i < heightin; i++) {
208
 
         GLubyte *ubptr = (GLubyte *) datain
209
 
            + i * rowstride
210
 
            + unpackskiprows * rowstride + unpackskippixels * components;
211
 
         for (j = 0; j < widthin * components; j++) {
212
 
            dummy(j, k);
213
 
            tempin[k++] = (GLfloat) * ubptr++;
214
 
         }
215
 
      }
216
 
      break;
217
 
   case GL_BYTE:
218
 
      k = 0;
219
 
      for (i = 0; i < heightin; i++) {
220
 
         GLbyte *bptr = (GLbyte *) datain
221
 
            + i * rowstride
222
 
            + unpackskiprows * rowstride + unpackskippixels * components;
223
 
         for (j = 0; j < widthin * components; j++) {
224
 
            dummy(j, k);
225
 
            tempin[k++] = (GLfloat) * bptr++;
226
 
         }
227
 
      }
228
 
      break;
229
 
   case GL_UNSIGNED_SHORT:
230
 
      k = 0;
231
 
      for (i = 0; i < heightin; i++) {
232
 
         GLushort *usptr = (GLushort *) datain
233
 
            + i * rowstride
234
 
            + unpackskiprows * rowstride + unpackskippixels * components;
235
 
         for (j = 0; j < widthin * components; j++) {
236
 
            dummy(j, k);
237
 
            tempin[k++] = (GLfloat) * usptr++;
238
 
         }
239
 
      }
240
 
      break;
241
 
   case GL_SHORT:
242
 
      k = 0;
243
 
      for (i = 0; i < heightin; i++) {
244
 
         GLshort *sptr = (GLshort *) datain
245
 
            + i * rowstride
246
 
            + unpackskiprows * rowstride + unpackskippixels * components;
247
 
         for (j = 0; j < widthin * components; j++) {
248
 
            dummy(j, k);
249
 
            tempin[k++] = (GLfloat) * sptr++;
250
 
         }
251
 
      }
252
 
      break;
253
 
   case GL_UNSIGNED_INT:
254
 
      k = 0;
255
 
      for (i = 0; i < heightin; i++) {
256
 
         GLuint *uiptr = (GLuint *) datain
257
 
            + i * rowstride
258
 
            + unpackskiprows * rowstride + unpackskippixels * components;
259
 
         for (j = 0; j < widthin * components; j++) {
260
 
            dummy(j, k);
261
 
            tempin[k++] = (GLfloat) * uiptr++;
262
 
         }
263
 
      }
264
 
      break;
265
 
   case GL_INT:
266
 
      k = 0;
267
 
      for (i = 0; i < heightin; i++) {
268
 
         GLint *iptr = (GLint *) datain
269
 
            + i * rowstride
270
 
            + unpackskiprows * rowstride + unpackskippixels * components;
271
 
         for (j = 0; j < widthin * components; j++) {
272
 
            dummy(j, k);
273
 
            tempin[k++] = (GLfloat) * iptr++;
274
 
         }
275
 
      }
276
 
      break;
277
 
   case GL_FLOAT:
278
 
      k = 0;
279
 
      for (i = 0; i < heightin; i++) {
280
 
         GLfloat *fptr = (GLfloat *) datain
281
 
            + i * rowstride
282
 
            + unpackskiprows * rowstride + unpackskippixels * components;
283
 
         for (j = 0; j < widthin * components; j++) {
284
 
            dummy(j, k);
285
 
            tempin[k++] = *fptr++;
286
 
         }
287
 
      }
288
 
      break;
289
 
   default:
290
 
      return GLU_INVALID_ENUM;
291
 
   }
292
 
 
293
 
 
294
 
   /*
295
 
    * Scale the image!
296
 
    */
297
 
 
298
 
   if (widthout > 1)
299
 
      sx = (GLfloat) (widthin - 1) / (GLfloat) (widthout - 1);
300
 
   else
301
 
      sx = (GLfloat) (widthin - 1);
302
 
   if (heightout > 1)
303
 
      sy = (GLfloat) (heightin - 1) / (GLfloat) (heightout - 1);
304
 
   else
305
 
      sy = (GLfloat) (heightin - 1);
306
 
 
307
 
/*#define POINT_SAMPLE*/
308
 
#ifdef POINT_SAMPLE
309
 
   for (i = 0; i < heightout; i++) {
310
 
      GLint ii = i * sy;
311
 
      for (j = 0; j < widthout; j++) {
312
 
         GLint jj = j * sx;
313
 
 
314
 
         GLfloat *src = tempin + (ii * widthin + jj) * components;
315
 
         GLfloat *dst = tempout + (i * widthout + j) * components;
316
 
 
317
 
         for (k = 0; k < components; k++) {
318
 
            *dst++ = *src++;
319
 
         }
320
 
      }
321
 
   }
322
 
#else
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;
326
 
      GLfloat alpha, beta;
327
 
      GLfloat *src00, *src01, *src10, *src11;
328
 
      GLfloat s1, s2;
329
 
      GLfloat *dst;
330
 
 
331
 
      for (i = 0; i < heightout; i++) {
332
 
         i0 = i * sy;
333
 
         i1 = i0 + 1;
334
 
         if (i1 >= heightin)
335
 
            i1 = heightin - 1;
336
 
/*       i1 = (i+1) * sy - EPSILON;*/
337
 
         alpha = i * sy - i0;
338
 
         for (j = 0; j < widthout; j++) {
339
 
            j0 = j * sx;
340
 
            j1 = j0 + 1;
341
 
            if (j1 >= widthin)
342
 
               j1 = widthin - 1;
343
 
/*          j1 = (j+1) * sx - EPSILON; */
344
 
            beta = j * sx - j0;
345
 
 
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;
351
 
 
352
 
            dst = tempout + (i * widthout + j) * components;
353
 
 
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;
358
 
            }
359
 
         }
360
 
      }
361
 
   }
362
 
   else {
363
 
      /* shrink width and/or height:  use an unweighted box filter */
364
 
      GLint i0, i1;
365
 
      GLint j0, j1;
366
 
      GLint ii, jj;
367
 
      GLfloat sum, *dst;
368
 
 
369
 
      for (i = 0; i < heightout; i++) {
370
 
         i0 = i * sy;
371
 
         i1 = i0 + 1;
372
 
         if (i1 >= heightin)
373
 
            i1 = heightin - 1;
374
 
/*       i1 = (i+1) * sy - EPSILON; */
375
 
         for (j = 0; j < widthout; j++) {
376
 
            j0 = j * sx;
377
 
            j1 = j0 + 1;
378
 
            if (j1 >= widthin)
379
 
               j1 = widthin - 1;
380
 
/*          j1 = (j+1) * sx - EPSILON; */
381
 
 
382
 
            dst = tempout + (i * widthout + j) * components;
383
 
 
384
 
            /* compute average of pixels in the rectangle (i0,j0)-(i1,j1) */
385
 
            for (k = 0; k < components; k++) {
386
 
               sum = 0.0;
387
 
               for (ii = i0; ii <= i1; ii++) {
388
 
                  for (jj = j0; jj <= j1; jj++) {
389
 
                     sum += *(tempin + (ii * widthin + jj) * components + k);
390
 
                  }
391
 
               }
392
 
               sum /= (j1 - j0 + 1) * (i1 - i0 + 1);
393
 
               *dst++ = sum;
394
 
            }
395
 
         }
396
 
      }
397
 
   }
398
 
#endif
399
 
 
400
 
 
401
 
   /*
402
 
    * Return output image
403
 
    */
404
 
 
405
 
   if (packrowlength > 0) {
406
 
      rowlen = packrowlength;
407
 
   }
408
 
   else {
409
 
      rowlen = widthout;
410
 
   }
411
 
   if (sizeout >= packalignment) {
412
 
      rowstride = components * rowlen;
413
 
   }
414
 
   else {
415
 
      rowstride = packalignment / sizeout
416
 
         * CEILING(components * rowlen * sizeout, packalignment);
417
 
   }
418
 
 
419
 
   switch (typeout) {
420
 
   case GL_UNSIGNED_BYTE:
421
 
      k = 0;
422
 
      for (i = 0; i < heightout; i++) {
423
 
         GLubyte *ubptr = (GLubyte *) dataout
424
 
            + i * rowstride
425
 
            + packskiprows * rowstride + packskippixels * components;
426
 
         for (j = 0; j < widthout * components; j++) {
427
 
            dummy(j, k + i);
428
 
            *ubptr++ = (GLubyte) tempout[k++];
429
 
         }
430
 
      }
431
 
      break;
432
 
   case GL_BYTE:
433
 
      k = 0;
434
 
      for (i = 0; i < heightout; i++) {
435
 
         GLbyte *bptr = (GLbyte *) dataout
436
 
            + i * rowstride
437
 
            + packskiprows * rowstride + packskippixels * components;
438
 
         for (j = 0; j < widthout * components; j++) {
439
 
            dummy(j, k + i);
440
 
            *bptr++ = (GLbyte) tempout[k++];
441
 
         }
442
 
      }
443
 
      break;
444
 
   case GL_UNSIGNED_SHORT:
445
 
      k = 0;
446
 
      for (i = 0; i < heightout; i++) {
447
 
         GLushort *usptr = (GLushort *) dataout
448
 
            + i * rowstride
449
 
            + packskiprows * rowstride + packskippixels * components;
450
 
         for (j = 0; j < widthout * components; j++) {
451
 
            dummy(j, k + i);
452
 
            *usptr++ = (GLushort) tempout[k++];
453
 
         }
454
 
      }
455
 
      break;
456
 
   case GL_SHORT:
457
 
      k = 0;
458
 
      for (i = 0; i < heightout; i++) {
459
 
         GLshort *sptr = (GLshort *) dataout
460
 
            + i * rowstride
461
 
            + packskiprows * rowstride + packskippixels * components;
462
 
         for (j = 0; j < widthout * components; j++) {
463
 
            dummy(j, k + i);
464
 
            *sptr++ = (GLshort) tempout[k++];
465
 
         }
466
 
      }
467
 
      break;
468
 
   case GL_UNSIGNED_INT:
469
 
      k = 0;
470
 
      for (i = 0; i < heightout; i++) {
471
 
         GLuint *uiptr = (GLuint *) dataout
472
 
            + i * rowstride
473
 
            + packskiprows * rowstride + packskippixels * components;
474
 
         for (j = 0; j < widthout * components; j++) {
475
 
            dummy(j, k + i);
476
 
            *uiptr++ = (GLuint) tempout[k++];
477
 
         }
478
 
      }
479
 
      break;
480
 
   case GL_INT:
481
 
      k = 0;
482
 
      for (i = 0; i < heightout; i++) {
483
 
         GLint *iptr = (GLint *) dataout
484
 
            + i * rowstride
485
 
            + packskiprows * rowstride + packskippixels * components;
486
 
         for (j = 0; j < widthout * components; j++) {
487
 
            dummy(j, k + i);
488
 
            *iptr++ = (GLint) tempout[k++];
489
 
         }
490
 
      }
491
 
      break;
492
 
   case GL_FLOAT:
493
 
      k = 0;
494
 
      for (i = 0; i < heightout; i++) {
495
 
         GLfloat *fptr = (GLfloat *) dataout
496
 
            + i * rowstride
497
 
            + packskiprows * rowstride + packskippixels * components;
498
 
         for (j = 0; j < widthout * components; j++) {
499
 
            dummy(j, k + i);
500
 
            *fptr++ = tempout[k++];
501
 
         }
502
 
      }
503
 
      break;
504
 
   default:
505
 
      return GLU_INVALID_ENUM;
506
 
   }
507
 
 
508
 
 
509
 
   /* free temporary image storage */
510
 
   free(tempin);
511
 
   free(tempout);
512
 
 
513
 
   return 0;
514
 
}
515
 
 
516
 
 
517
 
 
518
 
/*
519
 
 * Return the largest k such that 2^k <= n.
520
 
 */
521
 
static GLint
522
 
ilog2(GLint n)
523
 
{
524
 
   GLint k;
525
 
 
526
 
   if (n <= 0)
527
 
      return 0;
528
 
   for (k = 0; n >>= 1; k++);
529
 
   return k;
530
 
}
531
 
 
532
 
 
533
 
 
534
 
/*
535
 
 * Find the value nearest to n which is also a power of two.
536
 
 */
537
 
static GLint
538
 
round2(GLint n)
539
 
{
540
 
   GLint m;
541
 
 
542
 
   for (m = 1; m < n; m *= 2);
543
 
 
544
 
   /* m>=n */
545
 
   if (m - n <= n - m / 2) {
546
 
      return m;
547
 
   }
548
 
   else {
549
 
      return m / 2;
550
 
   }
551
 
}
552
 
 
553
 
 
554
 
/*
555
 
 * Given an pixel format and datatype, return the number of bytes to
556
 
 * store one pixel.
557
 
 */
558
 
static GLint
559
 
bytes_per_pixel(GLenum format, GLenum type)
560
 
{
561
 
   GLint n, m;
562
 
 
563
 
   switch (format) {
564
 
   case GL_COLOR_INDEX:
565
 
   case GL_STENCIL_INDEX:
566
 
   case GL_DEPTH_COMPONENT:
567
 
   case GL_RED:
568
 
   case GL_GREEN:
569
 
   case GL_BLUE:
570
 
   case GL_ALPHA:
571
 
   case GL_LUMINANCE:
572
 
      n = 1;
573
 
      break;
574
 
   case GL_LUMINANCE_ALPHA:
575
 
      n = 2;
576
 
      break;
577
 
   case GL_RGB:
578
 
   case GL_BGR:
579
 
      n = 3;
580
 
      break;
581
 
   case GL_RGBA:
582
 
   case GL_BGRA:
583
 
#ifdef GL_EXT_abgr
584
 
   case GL_ABGR_EXT:
585
 
#endif
586
 
      n = 4;
587
 
      break;
588
 
   default:
589
 
      n = 0;
590
 
   }
591
 
 
592
 
   switch (type) {
593
 
   case GL_UNSIGNED_BYTE:
594
 
      m = sizeof(GLubyte);
595
 
      break;
596
 
   case GL_BYTE:
597
 
      m = sizeof(GLbyte);
598
 
      break;
599
 
   case GL_BITMAP:
600
 
      m = 1;
601
 
      break;
602
 
   case GL_UNSIGNED_SHORT:
603
 
      m = sizeof(GLushort);
604
 
      break;
605
 
   case GL_SHORT:
606
 
      m = sizeof(GLshort);
607
 
      break;
608
 
   case GL_UNSIGNED_INT:
609
 
      m = sizeof(GLuint);
610
 
      break;
611
 
   case GL_INT:
612
 
      m = sizeof(GLint);
613
 
      break;
614
 
   case GL_FLOAT:
615
 
      m = sizeof(GLfloat);
616
 
      break;
617
 
   default:
618
 
      m = 0;
619
 
   }
620
 
 
621
 
   return n * m;
622
 
}
623
 
 
624
 
 
625
 
 
626
 
/*
627
 
 * WARNING: This function isn't finished and has never been tested!!!!
628
 
 */
629
 
GLint GLAPIENTRY
630
 
gluBuild1DMipmaps(GLenum target, GLint components,
631
 
                  GLsizei width, GLenum format, GLenum type, const void *data)
632
 
{
633
 
   GLubyte *texture;
634
 
   GLint levels, max_levels;
635
 
   GLint new_width, max_width;
636
 
   GLint i, j, k, l;
637
 
 
638
 
   if (width < 1)
639
 
      return GLU_INVALID_VALUE;
640
 
 
641
 
   glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_width);
642
 
   max_levels = ilog2(max_width) + 1;
643
 
 
644
 
   /* Compute how many mipmap images to make */
645
 
   levels = ilog2(width) + 1;
646
 
   if (levels > max_levels) {
647
 
      levels = max_levels;
648
 
   }
649
 
 
650
 
   new_width = 1 << (levels - 1);
651
 
 
652
 
   texture = (GLubyte *) malloc(new_width * components);
653
 
   if (!texture) {
654
 
      return GLU_OUT_OF_MEMORY;
655
 
   }
656
 
 
657
 
   if (width != new_width) {
658
 
      /* initial rescaling */
659
 
      switch (type) {
660
 
      case GL_UNSIGNED_BYTE:
661
 
         {
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];
667
 
               }
668
 
            }
669
 
         }
670
 
         break;
671
 
      default:
672
 
         /* Not implemented */
673
 
         return GLU_ERROR;
674
 
      }
675
 
   }
676
 
 
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);
681
 
 
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);
690
 
         }
691
 
      }
692
 
   }
693
 
 
694
 
   free(texture);
695
 
 
696
 
   return 0;
697
 
}
698
 
 
699
 
 
700
 
 
701
 
GLint GLAPIENTRY
702
 
gluBuild2DMipmaps(GLenum target, GLint components,
703
 
                  GLsizei width, GLsizei height, GLenum format,
704
 
                  GLenum type, const void *data)
705
 
{
706
 
   GLint w, h, maxsize;
707
 
   void *image, *newimage;
708
 
   GLint neww, newh, level, bpp;
709
 
   int error;
710
 
   GLboolean done;
711
 
   GLint retval = 0;
712
 
   GLint unpackrowlength, unpackalignment, unpackskiprows, unpackskippixels;
713
 
   GLint packrowlength, packalignment, packskiprows, packskippixels;
714
 
 
715
 
   if (width < 1 || height < 1)
716
 
      return GLU_INVALID_VALUE;
717
 
 
718
 
   glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxsize);
719
 
 
720
 
   w = round2(width);
721
 
   if (w > maxsize) {
722
 
      w = maxsize;
723
 
   }
724
 
   h = round2(height);
725
 
   if (h > maxsize) {
726
 
      h = maxsize;
727
 
   }
728
 
 
729
 
   bpp = bytes_per_pixel(format, type);
730
 
   if (bpp == 0) {
731
 
      /* probably a bad format or type enum */
732
 
      return GLU_INVALID_ENUM;
733
 
   }
734
 
 
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);
744
 
 
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);
750
 
 
751
 
   done = GL_FALSE;
752
 
 
753
 
   if (w != width || h != height) {
754
 
      /* must rescale image to get "top" mipmap texture image */
755
 
      image = malloc((w + 4) * h * bpp);
756
 
      if (!image) {
757
 
         return GLU_OUT_OF_MEMORY;
758
 
      }
759
 
      error = gluScaleImage(format, width, height, type, data,
760
 
                            w, h, type, image);
761
 
      if (error) {
762
 
         retval = error;
763
 
         done = GL_TRUE;
764
 
      }
765
 
   }
766
 
   else {
767
 
      image = (void *) data;
768
 
   }
769
 
 
770
 
   level = 0;
771
 
   while (!done) {
772
 
      if (image != 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);
778
 
      }
779
 
 
780
 
      glTexImage2D(target, level, components, w, h, 0, format, type, image);
781
 
 
782
 
      if (w == 1 && h == 1)
783
 
         break;
784
 
 
785
 
      neww = (w < 2) ? 1 : w / 2;
786
 
      newh = (h < 2) ? 1 : h / 2;
787
 
      newimage = malloc((neww + 4) * newh * bpp);
788
 
      if (!newimage) {
789
 
         return GLU_OUT_OF_MEMORY;
790
 
      }
791
 
 
792
 
      error = gluScaleImage(format, w, h, type, image,
793
 
                            neww, newh, type, newimage);
794
 
      if (error) {
795
 
         retval = error;
796
 
         done = GL_TRUE;
797
 
      }
798
 
 
799
 
      if (image != data) {
800
 
         free(image);
801
 
      }
802
 
      image = newimage;
803
 
 
804
 
      w = neww;
805
 
      h = newh;
806
 
      level++;
807
 
   }
808
 
 
809
 
   if (image != data) {
810
 
      free(image);
811
 
   }
812
 
 
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);
822
 
 
823
 
   return retval;
824
 
}