~ubuntu-branches/debian/squeeze/stellarium/squeeze

« back to all changes in this revision

Viewing changes to src/external/glues_stel/source/glues_mipmap.c

  • Committer: Bazaar Package Importer
  • Author(s): Cédric Delfosse
  • Date: 2010-07-31 15:44:02 UTC
  • mfrom: (1.2.5 upstream)
  • Revision ID: james.westby@ubuntu.com-20100731154402-511dojtyt5ycuizd
Tags: 0.10.5-1
* New upstream release (Closes: #586804)
* Remove 01_fix_pow10_function_check.diff, now applied upstream
* Remove 02_remove_unknown_locale_code.diff, no more needed
* Rendering of `old_style' landscapes fixed by upstream (Closes: #581657)
* Update debian/control:
  - Bump Standards-Version from 3.8.4 to 3.9.0
  - Add libqt4-sql-sqlite to Depends (Closes: #582726)
* Update debian/copyright:
  - Fix FSF address

Show diffs side-by-side

added added

removed removed

Lines of Context:
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
 
 * OpenGL ES CM 1.0 port of part of GLUES by Mike Gorchak <mike@malva.ua>
31
 
 */
32
 
 
33
 
#include <assert.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 <QtGlobal>
40
 
 
41
 
#ifdef Q_OS_WIN
42
 
#include "GLee.h"
43
 
#endif
44
 
 
45
 
#include "glues_mipmap.h"
46
 
 
47
 
typedef union
48
 
{
49
 
   unsigned char ub[4];
50
 
   unsigned short us[2];
51
 
   unsigned int ui;
52
 
   char b[4];
53
 
   short s[2];
54
 
   int i;
55
 
   float f;
56
 
} Type_Widget;
57
 
 
58
 
/* Pixel storage modes */
59
 
typedef struct
60
 
{
61
 
   GLint pack_alignment;
62
 
   GLint pack_row_length;
63
 
   GLint pack_skip_rows;
64
 
   GLint pack_skip_pixels;
65
 
   GLint pack_swap_bytes;
66
 
   GLint pack_image_height;
67
 
 
68
 
   GLint unpack_alignment;
69
 
   GLint unpack_row_length;
70
 
   GLint unpack_skip_rows;
71
 
   GLint unpack_skip_pixels;
72
 
   GLint unpack_swap_bytes;
73
 
   GLint unpack_image_height;
74
 
} PixelStorageModes;
75
 
 
76
 
static int gluesBuild2DMipmapLevelsCore(GLenum, GLint, GLsizei, GLsizei,
77
 
                                                                          GLsizei, GLsizei, GLenum, GLenum,
78
 
                                                                          GLint, GLint, GLint, const void*);
79
 
 
80
 
/*
81
 
 * internal function declarations
82
 
 */
83
 
static GLfloat bytes_per_element(GLenum type);
84
 
static GLint elements_per_group(GLenum format, GLenum type);
85
 
static GLint image_size(GLint width, GLint height, GLenum format, GLenum type);
86
 
 
87
 
static void scale_internal_ubyte(GLint components, GLint widthin,
88
 
                                                   GLint heightin, const GLubyte* datain,
89
 
                                                   GLint widthout, GLint heightout,
90
 
                                                   GLubyte* dataout, GLint element_size,
91
 
                                                   GLint ysize, GLint group_size);
92
 
 
93
 
static int checkMipmapArgs(GLenum, GLenum, GLenum);
94
 
static GLboolean legalFormat(GLenum);
95
 
static GLboolean legalType(GLenum);
96
 
static GLboolean isTypePackedPixel(GLenum);
97
 
static GLboolean isLegalFormatForPackedPixelType(GLenum, GLenum);
98
 
static GLboolean isLegalLevels(GLint, GLint, GLint, GLint);
99
 
static void closestFit(GLenum, GLint, GLint, GLint, GLenum, GLenum,
100
 
                                           GLint*, GLint*);
101
 
 
102
 
/* packedpixel type scale routines */
103
 
static void extract565(int, const void*, GLfloat []);
104
 
static void shove565(const GLfloat [], int ,void*);
105
 
static void extract4444(int, const void*, GLfloat []);
106
 
static void shove4444(const GLfloat [], int ,void*);
107
 
static void extract5551(int, const void*, GLfloat []);
108
 
static void shove5551(const GLfloat [], int ,void*);
109
 
static void scaleInternalPackedPixel(int,
110
 
                                                                         void (*)(int, const void*,GLfloat []),
111
 
                                                                         void (*)(const GLfloat [],int, void*),
112
 
                                                                         GLint,GLint, const void*,
113
 
                                                                         GLint,GLint,void*,GLint,GLint,GLint);
114
 
static void halveImagePackedPixel(int,
115
 
                                                                  void (*)(int, const void*,GLfloat []),
116
 
                                                                  void (*)(const GLfloat [],int, void*),
117
 
                                                                  GLint, GLint, const void*,
118
 
                                                                  void*, GLint, GLint, GLint);
119
 
static void halve1DimagePackedPixel(int,
120
 
                                                                        void (*)(int, const void*,GLfloat []),
121
 
                                                                        void (*)(const GLfloat [],int, void*),
122
 
                                                                        GLint, GLint, const void*,
123
 
                                                                        void*, GLint, GLint, GLint);
124
 
 
125
 
static void halve1Dimage_ubyte(GLint, GLuint, GLuint,const GLubyte*,
126
 
                                                           GLubyte*, GLint, GLint, GLint);
127
 
 
128
 
static void retrieveStoreModes(PixelStorageModes* psm)
129
 
{
130
 
   psm->unpack_alignment=1;
131
 
   psm->unpack_row_length=0;
132
 
   psm->unpack_skip_rows=0;
133
 
   psm->unpack_skip_pixels=0;
134
 
   psm->unpack_swap_bytes=0;
135
 
 
136
 
   psm->pack_alignment=1;
137
 
   psm->pack_row_length=0;
138
 
   psm->pack_skip_rows=0;
139
 
   psm->pack_skip_pixels=0;
140
 
   psm->pack_swap_bytes=0;
141
 
}
142
 
 
143
 
static int computeLog(GLuint value)
144
 
{
145
 
   int i=0;
146
 
 
147
 
   /* Error! */
148
 
   if (value==0)
149
 
   {
150
 
          return -1;
151
 
   }
152
 
 
153
 
   for (;;)
154
 
   {
155
 
          if (value & 1)
156
 
          {
157
 
                 /* Error ! */
158
 
                 if (value!=1)
159
 
                 {
160
 
                        return -1;
161
 
                 }
162
 
                 return i;
163
 
          }
164
 
          value =value >> 1;
165
 
          i++;
166
 
   }
167
 
}
168
 
 
169
 
/*
170
 
** Compute the nearest power of 2 number.  This algorithm is a little
171
 
** strange, but it works quite well.
172
 
*/
173
 
static int nearestPower(GLuint value)
174
 
{
175
 
   int i=1;
176
 
 
177
 
   /* Error! */
178
 
   if (value==0)
179
 
   {
180
 
          return -1;
181
 
   }
182
 
 
183
 
   for (;;)
184
 
   {
185
 
          if (value==1)
186
 
          {
187
 
                 return i;
188
 
          }
189
 
          else
190
 
          {
191
 
                 if (value==3)
192
 
                 {
193
 
                        return i*4;
194
 
                 }
195
 
          }
196
 
          value=value>>1;
197
 
          i*=2;
198
 
   }
199
 
}
200
 
 
201
 
#define __GLUES_SWAP_2_BYTES(s)\
202
 
(GLushort)(((GLushort)((const GLubyte*)(s))[1])<<8 | ((const GLubyte*)(s))[0])
203
 
 
204
 
#define __GLUES_SWAP_4_BYTES(s)\
205
 
(GLuint)(((GLuint)((const GLubyte*)(s))[3])<<24 | \
206
 
                ((GLuint)((const GLubyte*)(s))[2])<<16 | \
207
 
                ((GLuint)((const GLubyte*)(s))[1])<<8  | ((const GLubyte*)(s))[0])
208
 
 
209
 
static void halveImage_ubyte(GLint components, GLuint width, GLuint height,
210
 
                                                const GLubyte* datain, GLubyte* dataout,
211
 
                                                GLint element_size, GLint ysize, GLint group_size)
212
 
{
213
 
   int i, j, k;
214
 
   int newwidth, newheight;
215
 
   int padBytes;
216
 
   GLubyte* s;
217
 
   const char* t;
218
 
 
219
 
   /* handle case where there is only 1 column/row */
220
 
   if (width==1 || height==1)
221
 
   {
222
 
          assert(!(width==1 && height==1) ); /* can't be 1x1 */
223
 
          halve1Dimage_ubyte(components, width, height, datain, dataout, element_size, ysize, group_size);
224
 
          return;
225
 
   }
226
 
 
227
 
   newwidth=width/2;
228
 
   newheight=height/2;
229
 
   padBytes=ysize-(width*group_size);
230
 
   s=dataout;
231
 
   t=(const char*)datain;
232
 
 
233
 
   /* Piece o' cake! */
234
 
   for (i=0; i<newheight; i++)
235
 
   {
236
 
          for (j=0; j<newwidth; j++)
237
 
          {
238
 
                 for (k=0; k<components; k++)
239
 
                 {
240
 
                        s[0]=(*(const GLubyte*)t+
241
 
                                  *(const GLubyte*)(t+group_size)+
242
 
                                  *(const GLubyte*)(t+ysize)+
243
 
                                  *(const GLubyte*)(t+ysize+group_size)+2)/4;
244
 
                                  s++; t+=element_size;
245
 
                 }
246
 
                 t+=group_size;
247
 
          }
248
 
          t+=padBytes;
249
 
          t+=ysize;
250
 
   }
251
 
}
252
 
 
253
 
/* */
254
 
static void halve1Dimage_ubyte(GLint components, GLuint width, GLuint height,
255
 
                                                           const GLubyte* dataIn, GLubyte* dataOut,
256
 
                                                           GLint element_size, GLint ysize,
257
 
                                                           GLint group_size)
258
 
{
259
 
   GLint halfWidth=width/2;
260
 
   GLint halfHeight=height/2;
261
 
   const char* src=(const char*)dataIn;
262
 
   GLubyte* dest=dataOut;
263
 
   int jj;
264
 
 
265
 
   assert(width==1 || height==1); /* must be 1D */
266
 
   assert(width!=height);         /* can't be square */
267
 
 
268
 
   if (height==1)
269
 
   {                              /* 1 row */
270
 
          assert(width!=1);           /* widthxheight can't be 1x1 */
271
 
          halfHeight=1;
272
 
 
273
 
          for (jj=0; jj<halfWidth; jj++)
274
 
          {
275
 
                 int kk;
276
 
                 for (kk=0; kk<components; kk++)
277
 
                 {
278
 
                        *dest=(*(const GLubyte*)src+
279
 
                                   *(const GLubyte*)(src+group_size))/2;
280
 
 
281
 
                        src+=element_size;
282
 
                        dest++;
283
 
                 }
284
 
                 src+=group_size;         /* skip to next 2 */
285
 
          }
286
 
          {
287
 
                 int padBytes=ysize-(width*group_size);
288
 
                 src+=padBytes;           /* for assertion only */
289
 
          }
290
 
   }
291
 
   else
292
 
   {
293
 
          if (width==1)
294
 
          {                           /* 1 column */
295
 
                 int padBytes=ysize-(width*group_size);
296
 
                 assert(height!=1);       /* widthxheight can't be 1x1 */
297
 
                 halfWidth=1;
298
 
 
299
 
                 /* one vertical column with possible pad bytes per row */
300
 
                 /* average two at a time */
301
 
                 for (jj=0; jj<halfHeight; jj++)
302
 
                 {
303
 
                        int kk;
304
 
 
305
 
                        for (kk=0; kk<components; kk++)
306
 
                        {
307
 
                           *dest=(*(const GLubyte*)src+*(const GLubyte*)(src+ysize))/2;
308
 
 
309
 
                           src+=element_size;
310
 
                           dest++;
311
 
                        }
312
 
                        src+=padBytes; /* add pad bytes, if any, to get to end to row */
313
 
                        src+=ysize;
314
 
                 }
315
 
          }
316
 
   }
317
 
 
318
 
   assert(src==&((const char*)dataIn)[ysize*height]);
319
 
   assert((char*)dest==&((char*)dataOut)[components*element_size*halfWidth*halfHeight]);
320
 
} /* halve1Dimage_ubyte() */
321
 
 
322
 
 
323
 
static void scale_internal_ubyte(GLint components, GLint widthin,
324
 
                                                                 GLint heightin, const GLubyte* datain,
325
 
                                                                 GLint widthout, GLint heightout,
326
 
                                                                 GLubyte* dataout, GLint element_size,
327
 
                                                                 GLint ysize, GLint group_size)
328
 
{
329
 
   float convx;
330
 
   float convy;
331
 
   float percent;
332
 
 
333
 
   /* Max components in a format is 4, so... */
334
 
   float totals[4];
335
 
   float area;
336
 
   int i, j, k, xindex;
337
 
 
338
 
   const char* temp;
339
 
   const char* temp0;
340
 
   const char* temp_index;
341
 
   int outindex;
342
 
 
343
 
   int lowx_int, highx_int, lowy_int, highy_int;
344
 
   float x_percent, y_percent;
345
 
   float lowx_float, highx_float, lowy_float, highy_float;
346
 
   float convy_float, convx_float;
347
 
   int convy_int, convx_int;
348
 
   int l, m;
349
 
   const char* left;
350
 
   const char* right;
351
 
 
352
 
   if (widthin==widthout*2 && heightin==heightout*2)
353
 
   {
354
 
          halveImage_ubyte(components, widthin, heightin, (const GLubyte*)datain,
355
 
                                          (GLubyte*)dataout, element_size, ysize, group_size);
356
 
          return;
357
 
   }
358
 
 
359
 
   convy=(float)heightin/heightout;
360
 
   convx=(float)widthin/widthout;
361
 
   convy_int=(int)floor(convy);
362
 
   convy_float=convy-convy_int;
363
 
   convx_int=(int)floor(convx);
364
 
   convx_float=convx-convx_int;
365
 
 
366
 
   area=convx*convy;
367
 
 
368
 
   lowy_int=0;
369
 
   lowy_float=0;
370
 
   highy_int=convy_int;
371
 
   highy_float=convy_float;
372
 
 
373
 
   for (i=0; i<heightout; i++)
374
 
   {
375
 
          /* Clamp here to be sure we don't read beyond input buffer. */
376
 
          if (highy_int>=heightin)
377
 
          {
378
 
                 highy_int=heightin-1;
379
 
          }
380
 
          lowx_int = 0;
381
 
          lowx_float = 0;
382
 
          highx_int = convx_int;
383
 
          highx_float = convx_float;
384
 
 
385
 
          for (j=0; j<widthout; j++)
386
 
          {
387
 
                 /*
388
 
                 ** Ok, now apply box filter to box that goes from (lowx, lowy)
389
 
                 ** to (highx, highy) on input data into this pixel on output
390
 
                 ** data.
391
 
                 */
392
 
                 totals[0] = totals[1] = totals[2] = totals[3] = 0.0;
393
 
 
394
 
                 /* calculate the value for pixels in the 1st row */
395
 
                 xindex=lowx_int*group_size;
396
 
                 if ((highy_int>lowy_int) && (highx_int>lowx_int))
397
 
                 {
398
 
                        y_percent=1-lowy_float;
399
 
                        temp=(const char*)datain+xindex+lowy_int*ysize;
400
 
                        percent=y_percent*(1-lowx_float);
401
 
                        for (k=0, temp_index=temp; k<components; k++, temp_index+=element_size)
402
 
                        {
403
 
                           totals[k]+=(GLubyte)(*(temp_index))*percent;
404
 
                        }
405
 
 
406
 
                        left=temp;
407
 
                        for(l=lowx_int+1; l<highx_int; l++)
408
 
                        {
409
 
                           temp+=group_size;
410
 
                           for (k=0, temp_index=temp; k<components; k++, temp_index+=element_size)
411
 
                           {
412
 
                                  totals[k]+=(GLubyte)(*(temp_index))*y_percent;
413
 
                           }
414
 
                        }
415
 
 
416
 
                        temp+=group_size;
417
 
                        right=temp;
418
 
                        percent=y_percent*highx_float;
419
 
                        for (k=0, temp_index=temp; k<components; k++, temp_index+=element_size)
420
 
                        {
421
 
                           totals[k]+=(GLubyte)(*(temp_index))*percent;
422
 
                        }
423
 
 
424
 
                        /* calculate the value for pixels in the last row */
425
 
                        y_percent=highy_float;
426
 
                        percent=y_percent*(1-lowx_float);
427
 
                        temp=(const char*)datain+xindex+highy_int*ysize;
428
 
                        for (k=0, temp_index=temp; k<components; k++, temp_index+=element_size)
429
 
                        {
430
 
                           totals[k]+=(GLubyte)(*(temp_index))*percent;
431
 
                        }
432
 
                        for (l=lowx_int+1; l<highx_int; l++)
433
 
                        {
434
 
                           temp+=group_size;
435
 
                           for (k=0, temp_index=temp; k<components; k++, temp_index+=element_size)
436
 
                           {
437
 
                                  totals[k]+=(GLubyte)(*(temp_index))*y_percent;
438
 
                           }
439
 
                        }
440
 
                        temp+=group_size;
441
 
                        percent=y_percent*highx_float;
442
 
                        for (k=0, temp_index=temp; k<components; k++, temp_index+=element_size)
443
 
                        {
444
 
                           totals[k]+=(GLubyte)(*(temp_index))*percent;
445
 
                        }
446
 
 
447
 
                        /* calculate the value for pixels in the 1st and last column */
448
 
                        for (m=lowy_int+1; m<highy_int; m++)
449
 
                        {
450
 
                           left+=ysize;
451
 
                           right+=ysize;
452
 
                           for (k=0; k<components; k++, left+=element_size, right+=element_size)
453
 
                           {
454
 
                                  totals[k]+=(GLubyte)(*(left))*(1-lowx_float)+(GLubyte)(*(right))*highx_float;
455
 
                           }
456
 
                        }
457
 
                 }
458
 
                 else
459
 
                 {
460
 
                        if (highy_int>lowy_int)
461
 
                        {
462
 
                           x_percent=highx_float-lowx_float;
463
 
                           percent=(1-lowy_float)*x_percent;
464
 
                           temp=(const char*)datain+xindex+lowy_int*ysize;
465
 
                           for (k=0, temp_index=temp; k<components; k++, temp_index+=element_size)
466
 
                           {
467
 
                                  totals[k]+=(GLubyte)(*(temp_index))*percent;
468
 
                           }
469
 
                           for (m=lowy_int+1; m<highy_int; m++)
470
 
                           {
471
 
                                  temp+=ysize;
472
 
                                  for (k=0, temp_index=temp; k<components; k++, temp_index+=element_size)
473
 
                                  {
474
 
                                         totals[k]+=(GLubyte)(*(temp_index))*x_percent;
475
 
                                  }
476
 
                           }
477
 
                           percent = x_percent * highy_float;
478
 
                           temp+=ysize;
479
 
                           for (k=0, temp_index=temp; k<components; k++, temp_index+=element_size)
480
 
                           {
481
 
                                  totals[k]+=(GLubyte)(*(temp_index))*percent;
482
 
                           }
483
 
                        }
484
 
                        else
485
 
                        {
486
 
                           if (highx_int>lowx_int)
487
 
                           {
488
 
                                  y_percent=highy_float-lowy_float;
489
 
                                  percent=(1-lowx_float)*y_percent;
490
 
                                  temp=(const char*)datain+xindex+lowy_int*ysize;
491
 
                                  for (k=0, temp_index=temp; k<components; k++, temp_index+=element_size)
492
 
                                  {
493
 
                                         totals[k]+=(GLubyte)(*(temp_index))*percent;
494
 
                                  }
495
 
                                  for (l=lowx_int+1; l<highx_int; l++)
496
 
                                  {
497
 
                                         temp+=group_size;
498
 
                                         for (k=0, temp_index=temp; k<components; k++, temp_index+=element_size)
499
 
                                         {
500
 
                                                totals[k]+=(GLubyte)(*(temp_index))*y_percent;
501
 
                                         }
502
 
                                  }
503
 
                                  temp+=group_size;
504
 
                                  percent=y_percent*highx_float;
505
 
                                  for (k=0, temp_index=temp; k<components; k++, temp_index+=element_size)
506
 
                                  {
507
 
                                         totals[k] += (GLubyte)(*(temp_index)) * percent;
508
 
                                  }
509
 
                           }
510
 
                           else
511
 
                           {
512
 
                                  percent=(highy_float-lowy_float)*(highx_float-lowx_float);
513
 
                                  temp=(const char*)datain+xindex+lowy_int*ysize;
514
 
                                  for (k=0, temp_index=temp; k<components; k++, temp_index+=element_size)
515
 
                                  {
516
 
                                         totals[k]+=(GLubyte)(*(temp_index))*percent;
517
 
                                  }
518
 
                           }
519
 
                        }
520
 
                 }
521
 
 
522
 
                 /* this is for the pixels in the body */
523
 
                 temp0=(const char*)datain+xindex+group_size+(lowy_int+1)*ysize;
524
 
                 for (m=lowy_int+1; m<highy_int; m++)
525
 
                 {
526
 
                        temp=temp0;
527
 
                        for(l=lowx_int+1; l<highx_int; l++)
528
 
                        {
529
 
                           for (k=0, temp_index=temp; k<components; k++, temp_index+=element_size)
530
 
                           {
531
 
                                  totals[k]+=(GLubyte)(*(temp_index));
532
 
                           }
533
 
                           temp+=group_size;
534
 
                        }
535
 
                        temp0 += ysize;
536
 
                 }
537
 
 
538
 
                 outindex=(j+(i*widthout))*components;
539
 
                 for (k=0; k<components; k++)
540
 
                 {
541
 
                        dataout[outindex+k]=(GLubyte)(totals[k]/area);
542
 
                 }
543
 
                 lowx_int=highx_int;
544
 
                 lowx_float=highx_float;
545
 
                 highx_int += convx_int;
546
 
                 highx_float += convx_float;
547
 
                 if (highx_float>1)
548
 
                 {
549
 
                        highx_float-=1.0;
550
 
                        highx_int++;
551
 
                 }
552
 
          }
553
 
          lowy_int=highy_int;
554
 
          lowy_float=highy_float;
555
 
          highy_int+=convy_int;
556
 
          highy_float+=convy_float;
557
 
          if (highy_float>1)
558
 
          {
559
 
                 highy_float-=1.0;
560
 
                 highy_int++;
561
 
          }
562
 
   }
563
 
}
564
 
 
565
 
static int checkMipmapArgs(GLenum internalFormat, GLenum format, GLenum type)
566
 
{
567
 
   if (!legalFormat(format) || !legalType(type))
568
 
   {
569
 
          return GLUES_INVALID_ENUM;
570
 
   }
571
 
 
572
 
   if (!isLegalFormatForPackedPixelType(format, type))
573
 
   {
574
 
          return GLUES_INVALID_OPERATION;
575
 
   }
576
 
 
577
 
   return 0;
578
 
} /* checkMipmapArgs() */
579
 
 
580
 
static GLboolean legalFormat(GLenum format)
581
 
{
582
 
   switch(format)
583
 
   {
584
 
          case GL_ALPHA:
585
 
          case GL_RGB:
586
 
          case GL_RGBA:
587
 
          case GL_LUMINANCE:
588
 
          case GL_LUMINANCE_ALPHA:
589
 
                   return GL_TRUE;
590
 
          default:
591
 
                   return GL_FALSE;
592
 
   }
593
 
}
594
 
 
595
 
static GLboolean legalType(GLenum type)
596
 
{
597
 
   switch(type)
598
 
   {
599
 
          case GL_UNSIGNED_BYTE:
600
 
          case GL_UNSIGNED_SHORT_5_6_5:
601
 
          case GL_UNSIGNED_SHORT_4_4_4_4:
602
 
          case GL_UNSIGNED_SHORT_5_5_5_1:
603
 
                   return GL_TRUE;
604
 
          default:
605
 
                   return GL_FALSE;
606
 
   }
607
 
}
608
 
 
609
 
/* */
610
 
static GLboolean isTypePackedPixel(GLenum type)
611
 
{
612
 
   assert(legalType(type));
613
 
 
614
 
   if (type==GL_UNSIGNED_SHORT_5_6_5 ||
615
 
           type==GL_UNSIGNED_SHORT_4_4_4_4 ||
616
 
           type==GL_UNSIGNED_SHORT_5_5_5_1)
617
 
   {
618
 
          return 1;
619
 
   }
620
 
   else
621
 
   {
622
 
          return 0;
623
 
   }
624
 
} /* isTypePackedPixel() */
625
 
 
626
 
/* Determines if the packed pixel type is compatible with the format */
627
 
static GLboolean isLegalFormatForPackedPixelType(GLenum format, GLenum type)
628
 
{
629
 
   /* if not a packed pixel type then return true */
630
 
   if (!isTypePackedPixel(type))
631
 
   {
632
 
          return GL_TRUE;
633
 
   }
634
 
 
635
 
   /* 5_6_5 is only compatible with RGB */
636
 
   if ((type==GL_UNSIGNED_SHORT_5_6_5) && format!=GL_RGB)
637
 
   {
638
 
          return GL_FALSE;
639
 
   }
640
 
 
641
 
   /* 4_4_4_4 & 5_5_5_1
642
 
        * are only compatible with RGBA
643
 
        */
644
 
   if ((type==GL_UNSIGNED_SHORT_4_4_4_4 || type==GL_UNSIGNED_SHORT_5_5_5_1) &&
645
 
           (format != GL_RGBA))
646
 
   {
647
 
          return GL_FALSE;
648
 
   }
649
 
 
650
 
   return GL_TRUE;
651
 
} /* isLegalFormatForPackedPixelType() */
652
 
 
653
 
static GLboolean isLegalLevels(GLint userLevel,GLint baseLevel,GLint maxLevel,
654
 
                                                           GLint totalLevels)
655
 
{
656
 
   if (baseLevel < 0 || baseLevel < userLevel || maxLevel < baseLevel ||
657
 
           totalLevels < maxLevel)
658
 
   {
659
 
          return GL_FALSE;
660
 
   }
661
 
   else
662
 
   {
663
 
          return GL_TRUE;
664
 
   }
665
 
} /* isLegalLevels() */
666
 
 
667
 
/* Given user requested texture size, determine if it fits. If it
668
 
 * doesn't then halve both sides and make the determination again
669
 
 * until it does fit (for IR only).
670
 
 */
671
 
static void closestFit(GLenum target, GLint width, GLint height,
672
 
                                           GLint internalFormat, GLenum format, GLenum type,
673
 
                                           GLint *newWidth, GLint *newHeight)
674
 
{
675
 
   GLint maxsize;
676
 
 
677
 
   glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxsize);
678
 
 
679
 
   /* clamp user's texture sizes to maximum sizes, if necessary */
680
 
   *newWidth=nearestPower(width);
681
 
   if (*newWidth>maxsize)
682
 
   {
683
 
          *newWidth=maxsize;
684
 
   }
685
 
   *newHeight=nearestPower(height);
686
 
   if (*newHeight>maxsize)
687
 
   {
688
 
          *newHeight = maxsize;
689
 
   }
690
 
} /* closestFit() */
691
 
 
692
 
 
693
 
/* To make swapping images less error prone */
694
 
#define __GLUES_INIT_SWAP_IMAGE void* tmpImage
695
 
#define __GLUES_SWAP_IMAGE(a,b) tmpImage=a; a=b; b=tmpImage;
696
 
 
697
 
static int gluesBuild2DMipmapLevelsCore(GLenum target, GLint internalFormat,
698
 
                                                                          GLsizei width, GLsizei height,
699
 
                                                                          GLsizei widthPowerOf2,
700
 
                                                                          GLsizei heightPowerOf2,
701
 
                                                                          GLenum format, GLenum type,
702
 
                                                                          GLint userLevel,
703
 
                                                                          GLint baseLevel,GLint maxLevel,
704
 
                                                                          const void* data)
705
 
{
706
 
   GLint newwidth, newheight;
707
 
   GLint level, levels;
708
 
   const void* usersImage;     /* passed from user. Don't touch! */
709
 
   void* srcImage;
710
 
   void* dstImage;             /* scratch area to build mipmapped images */
711
 
   __GLUES_INIT_SWAP_IMAGE;
712
 
   GLint memreq;
713
 
   GLint cmpts;
714
 
 
715
 
   GLint myswap_bytes, groups_per_line, element_size, group_size;
716
 
   GLint rowsize, padding;
717
 
   PixelStorageModes psm;
718
 
 
719
 
   assert(checkMipmapArgs(internalFormat,format,type)==0);
720
 
   assert(width>=1 && height>=1);
721
 
 
722
 
   srcImage=dstImage=NULL;
723
 
 
724
 
   newwidth=widthPowerOf2;
725
 
   newheight=heightPowerOf2;
726
 
   levels=computeLog(newwidth);
727
 
   level=computeLog(newheight);
728
 
   if (level>levels)
729
 
   {
730
 
          levels=level;
731
 
   }
732
 
 
733
 
   levels+=userLevel;
734
 
 
735
 
   retrieveStoreModes(&psm);
736
 
   myswap_bytes=psm.unpack_swap_bytes;
737
 
   cmpts=elements_per_group(format,type);
738
 
   if (psm.unpack_row_length>0)
739
 
   {
740
 
          groups_per_line=psm.unpack_row_length;
741
 
   }
742
 
   else
743
 
   {
744
 
          groups_per_line=width;
745
 
   }
746
 
 
747
 
   element_size=(GLint)bytes_per_element(type);
748
 
   group_size=element_size*cmpts;
749
 
   if (element_size==1)
750
 
   {
751
 
          /* Nothing to swap */
752
 
          myswap_bytes=0;
753
 
   }
754
 
 
755
 
   rowsize=groups_per_line*group_size;
756
 
   padding=(rowsize%psm.unpack_alignment);
757
 
   if (padding)
758
 
   {
759
 
          rowsize+=psm.unpack_alignment-padding;
760
 
   }
761
 
   usersImage=(const GLubyte*)data+psm.unpack_skip_rows*rowsize+psm.unpack_skip_pixels*group_size;
762
 
 
763
 
   level=userLevel;
764
 
 
765
 
   /* already power-of-two square */
766
 
   if (width==newwidth && height==newheight)
767
 
   {
768
 
          /* Use usersImage for level userLevel */
769
 
          if (baseLevel<=level && level<=maxLevel)
770
 
          {
771
 
                 glTexImage2D(target, level, internalFormat, width,
772
 
                                          height, 0, format, type, usersImage);
773
 
          }
774
 
          if (levels==0)
775
 
          {
776
 
                 /* we're done. clean up and return */
777
 
                 glPixelStorei(GL_UNPACK_ALIGNMENT, psm.unpack_alignment);
778
 
                 return 0;
779
 
          }
780
 
 
781
 
          {
782
 
                 int nextWidth=newwidth/2;
783
 
                 int nextHeight=newheight/2;
784
 
 
785
 
                 /* clamp to 1 */
786
 
                 if (nextWidth<1)
787
 
                 {
788
 
                        nextWidth=1;
789
 
                 }
790
 
                 if (nextHeight<1)
791
 
                 {
792
 
                        nextHeight=1;
793
 
                 }
794
 
                 memreq=image_size(nextWidth, nextHeight, format, type);
795
 
          }
796
 
 
797
 
          switch(type)
798
 
          {
799
 
                 case GL_UNSIGNED_BYTE:
800
 
                          dstImage = (GLubyte *)malloc(memreq);
801
 
                          break;
802
 
                 case GL_UNSIGNED_SHORT_5_6_5:
803
 
                 case GL_UNSIGNED_SHORT_4_4_4_4:
804
 
                 case GL_UNSIGNED_SHORT_5_5_5_1:
805
 
                          dstImage = (GLushort *)malloc(memreq);
806
 
                          break;
807
 
                 default:
808
 
                          return GLUES_INVALID_ENUM;
809
 
          }
810
 
          if (dstImage==NULL)
811
 
          {
812
 
                 glPixelStorei(GL_UNPACK_ALIGNMENT, psm.unpack_alignment);
813
 
                 return GLUES_OUT_OF_MEMORY;
814
 
          }
815
 
          else
816
 
          {
817
 
                 switch(type)
818
 
                 {
819
 
                        case GL_UNSIGNED_BYTE:
820
 
                                 halveImage_ubyte(cmpts, width, height, (const GLubyte*)usersImage,
821
 
                                                                 (GLubyte*)dstImage, element_size, rowsize, group_size);
822
 
                                 break;
823
 
                        case GL_UNSIGNED_SHORT_5_6_5:
824
 
                                 halveImagePackedPixel(3, extract565, shove565, width, height,
825
 
                                                                           usersImage, dstImage, element_size,
826
 
                                                                           rowsize, myswap_bytes);
827
 
                                 break;
828
 
                        case GL_UNSIGNED_SHORT_4_4_4_4:
829
 
                                 halveImagePackedPixel(4, extract4444, shove4444, width, height,
830
 
                                                                           usersImage, dstImage, element_size,
831
 
                                                                           rowsize, myswap_bytes);
832
 
                                 break;
833
 
                        case GL_UNSIGNED_SHORT_5_5_5_1:
834
 
                                 halveImagePackedPixel(4, extract5551, shove5551, width, height,
835
 
                                                                           usersImage, dstImage, element_size,
836
 
                                                                           rowsize, myswap_bytes);
837
 
                                 break;
838
 
                        default:
839
 
                                 assert(0);
840
 
                                 break;
841
 
                 }
842
 
          }
843
 
 
844
 
          newwidth=width/2;
845
 
          newheight=height/2;
846
 
 
847
 
          /* clamp to 1 */
848
 
          if (newwidth<1)
849
 
          {
850
 
                 newwidth=1;
851
 
          }
852
 
          if (newheight<1)
853
 
          {
854
 
                 newheight=1;
855
 
          }
856
 
 
857
 
          myswap_bytes=0;
858
 
          rowsize=newwidth*group_size;
859
 
          memreq=image_size(newwidth, newheight, format, type);
860
 
          /* Swap srcImage and dstImage */
861
 
          __GLUES_SWAP_IMAGE(srcImage,dstImage);
862
 
          switch(type)
863
 
          {
864
 
                 case GL_UNSIGNED_BYTE:
865
 
                          dstImage=(GLubyte*)malloc(memreq);
866
 
                          break;
867
 
                 case GL_UNSIGNED_SHORT_5_6_5:
868
 
                 case GL_UNSIGNED_SHORT_4_4_4_4:
869
 
                 case GL_UNSIGNED_SHORT_5_5_5_1:
870
 
                          dstImage=(GLushort*)malloc(memreq);
871
 
                          break;
872
 
                 default:
873
 
                          return GLUES_INVALID_ENUM;
874
 
          }
875
 
          if (dstImage==NULL)
876
 
          {
877
 
                 glPixelStorei(GL_UNPACK_ALIGNMENT, psm.unpack_alignment);
878
 
                 return GLUES_OUT_OF_MEMORY;
879
 
          }
880
 
 
881
 
          /* level userLevel+1 is in srcImage; level userLevel already saved */
882
 
          level = userLevel+1;
883
 
   }
884
 
   else
885
 
   {
886
 
          /* user's image is *not* nice power-of-2 sized square */
887
 
          memreq=image_size(newwidth, newheight, format, type);
888
 
          switch(type)
889
 
          {
890
 
                 case GL_UNSIGNED_BYTE:
891
 
                          dstImage=(GLubyte*)malloc(memreq);
892
 
                          break;
893
 
                 case GL_UNSIGNED_SHORT_5_6_5:
894
 
                 case GL_UNSIGNED_SHORT_4_4_4_4:
895
 
                 case GL_UNSIGNED_SHORT_5_5_5_1:
896
 
                          dstImage=(GLushort*)malloc(memreq);
897
 
                          break;
898
 
                 default:
899
 
                          return GLUES_INVALID_ENUM;
900
 
          }
901
 
 
902
 
          if (dstImage==NULL)
903
 
          {
904
 
                 glPixelStorei(GL_UNPACK_ALIGNMENT, psm.unpack_alignment);
905
 
                 return GLUES_OUT_OF_MEMORY;
906
 
          }
907
 
 
908
 
          switch(type)
909
 
          {
910
 
                 case GL_UNSIGNED_BYTE:
911
 
                          scale_internal_ubyte(cmpts, width, height,
912
 
                                 (const GLubyte*)usersImage, newwidth, newheight,
913
 
                                 (GLubyte*)dstImage, element_size, rowsize, group_size);
914
 
                          break;
915
 
                 case GL_UNSIGNED_SHORT_5_6_5:
916
 
                          scaleInternalPackedPixel(3, extract565, shove565, width, height,
917
 
                                 usersImage, newwidth, newheight, (void*)dstImage, element_size,
918
 
                                 rowsize, myswap_bytes);
919
 
                          break;
920
 
                 case GL_UNSIGNED_SHORT_4_4_4_4:
921
 
                          scaleInternalPackedPixel(4, extract4444, shove4444, width, height,
922
 
                                 usersImage, newwidth, newheight, (void*)dstImage, element_size,
923
 
                                 rowsize,myswap_bytes);
924
 
                          break;
925
 
                 case GL_UNSIGNED_SHORT_5_5_5_1:
926
 
                          scaleInternalPackedPixel(4,extract5551, shove5551, width, height,
927
 
                                 usersImage, newwidth, newheight, (void*)dstImage, element_size,
928
 
                                 rowsize, myswap_bytes);
929
 
                          break;
930
 
                 default:
931
 
                          assert(0);
932
 
                          break;
933
 
          }
934
 
          myswap_bytes=0;
935
 
          rowsize=newwidth*group_size;
936
 
 
937
 
          /* Swap dstImage and srcImage */
938
 
          __GLUES_SWAP_IMAGE(srcImage,dstImage);
939
 
 
940
 
          /* use as little memory as possible */
941
 
          if (levels!=0)
942
 
          {
943
 
                 {
944
 
                        int nextWidth=newwidth/2;
945
 
                        int nextHeight=newheight/2;
946
 
 
947
 
                        if (nextWidth<1)
948
 
                        {
949
 
                           nextWidth=1;
950
 
                        }
951
 
                        if (nextHeight<1)
952
 
                        {
953
 
                           nextHeight=1;
954
 
                        }
955
 
 
956
 
                        memreq=image_size(nextWidth, nextHeight, format, type);
957
 
                 }
958
 
 
959
 
                 switch(type)
960
 
                 {
961
 
                        case GL_UNSIGNED_BYTE:
962
 
                                 dstImage = (GLubyte *)malloc(memreq);
963
 
                                 break;
964
 
                        case GL_UNSIGNED_SHORT_5_6_5:
965
 
                        case GL_UNSIGNED_SHORT_4_4_4_4:
966
 
                        case GL_UNSIGNED_SHORT_5_5_5_1:
967
 
                                 dstImage = (GLushort *)malloc(memreq);
968
 
                                 break;
969
 
                        default:
970
 
                                 return GLUES_INVALID_ENUM;
971
 
                 }
972
 
                 if (dstImage==NULL)
973
 
                 {
974
 
                        glPixelStorei(GL_UNPACK_ALIGNMENT, psm.unpack_alignment);
975
 
                        return GLUES_OUT_OF_MEMORY;
976
 
                 }
977
 
          }
978
 
 
979
 
          /* level userLevel is in srcImage; nothing saved yet */
980
 
          level=userLevel;
981
 
   }
982
 
 
983
 
   if (baseLevel<=level && level<=maxLevel)
984
 
   {
985
 
          glTexImage2D(target, level, internalFormat, newwidth, newheight, 0,
986
 
                                   format, type, (void*)srcImage);
987
 
   }
988
 
 
989
 
   level++; /* update current level for the loop */
990
 
   for (; level<=levels; level++)
991
 
   {
992
 
          switch(type)
993
 
          {
994
 
                 case GL_UNSIGNED_BYTE:
995
 
                          halveImage_ubyte(cmpts, newwidth, newheight, (GLubyte*)srcImage,
996
 
                                 (GLubyte *)dstImage, element_size, rowsize, group_size);
997
 
                          break;
998
 
                 case GL_UNSIGNED_SHORT_5_6_5:
999
 
                          halveImagePackedPixel(3, extract565, shove565, newwidth,
1000
 
                                 newheight, srcImage, dstImage, element_size, rowsize,
1001
 
                                 myswap_bytes);
1002
 
                          break;
1003
 
                 case GL_UNSIGNED_SHORT_4_4_4_4:
1004
 
                          halveImagePackedPixel(4, extract4444, shove4444, newwidth,
1005
 
                                 newheight, srcImage, dstImage, element_size, rowsize,
1006
 
                                 myswap_bytes);
1007
 
                          break;
1008
 
                 case GL_UNSIGNED_SHORT_5_5_5_1:
1009
 
                          halveImagePackedPixel(4, extract5551, shove5551, newwidth,
1010
 
                                 newheight, srcImage, dstImage, element_size, rowsize,
1011
 
                                 myswap_bytes);
1012
 
                          break;
1013
 
                 default:
1014
 
                          assert(0);
1015
 
                          break;
1016
 
          }
1017
 
 
1018
 
          __GLUES_SWAP_IMAGE(srcImage,dstImage);
1019
 
 
1020
 
          if (newwidth>1)
1021
 
          {
1022
 
                 newwidth/=2;
1023
 
                 rowsize/=2;
1024
 
          }
1025
 
          if (newheight>1)
1026
 
          {
1027
 
                 newheight/=2;
1028
 
          }
1029
 
 
1030
 
          {
1031
 
                 /* compute amount to pad per row, if any */
1032
 
                 int rowPad=rowsize%psm.unpack_alignment;
1033
 
 
1034
 
                 /* should row be padded? */
1035
 
                 if (rowPad == 0)
1036
 
                 {  /* nope, row should not be padded */
1037
 
                        /* call tex image with srcImage untouched since it's not padded */
1038
 
                        if (baseLevel<=level && level<=maxLevel)
1039
 
                        {
1040
 
                           glTexImage2D(target, level, internalFormat, newwidth, newheight,
1041
 
                                                        0, format, type, (void*) srcImage);
1042
 
                        }
1043
 
                 }
1044
 
                 else
1045
 
                 {  /* yes, row should be padded */
1046
 
                        /* compute length of new row in bytes, including padding */
1047
 
                        int newRowLength=rowsize+psm.unpack_alignment-rowPad;
1048
 
                        int ii;
1049
 
                        unsigned char* dstTrav;
1050
 
                        unsigned char* srcTrav; /* indices for copying */
1051
 
 
1052
 
                        /* allocate new image for mipmap of size newRowLength x newheight */
1053
 
                        void* newMipmapImage=malloc((size_t)(newRowLength*newheight));
1054
 
                        if (newMipmapImage==NULL)
1055
 
                        {
1056
 
                           /* out of memory so return */
1057
 
                           glPixelStorei(GL_UNPACK_ALIGNMENT, psm.unpack_alignment);
1058
 
                           return GLUES_OUT_OF_MEMORY;
1059
 
                        }
1060
 
 
1061
 
                        /* copy image from srcImage into newMipmapImage by rows */
1062
 
                        for (ii=0,
1063
 
                                 dstTrav=(unsigned char*) newMipmapImage,
1064
 
                                 srcTrav=(unsigned char*) srcImage;
1065
 
                                 ii<newheight;
1066
 
                                 ii++, dstTrav+= newRowLength, /* make sure the correct distance... */
1067
 
                                 srcTrav+= rowsize)
1068
 
                        {  /* ...is skipped */
1069
 
                           memcpy(dstTrav, srcTrav, rowsize);
1070
 
                           /* note that the pad bytes are not visited and will contain
1071
 
                                * garbage, which is ok.
1072
 
                                */
1073
 
                        }
1074
 
                        /* ...and use this new image for mipmapping instead */
1075
 
                        if (baseLevel<=level && level<=maxLevel)
1076
 
                        {
1077
 
                           glTexImage2D(target, level, internalFormat, newwidth, newheight,
1078
 
                                                        0, format, type, newMipmapImage);
1079
 
                        }
1080
 
                        free(newMipmapImage); /* don't forget to free it! */
1081
 
                 }
1082
 
          }
1083
 
   } /* for level */
1084
 
 
1085
 
   glPixelStorei(GL_UNPACK_ALIGNMENT, psm.unpack_alignment);
1086
 
 
1087
 
   free(srcImage); /*if you get to here, a srcImage has always been malloc'ed*/
1088
 
 
1089
 
   if (dstImage)
1090
 
   { /* if it's non-rectangular and only 1 level */
1091
 
          free(dstImage);
1092
 
   }
1093
 
 
1094
 
   return 0;
1095
 
} /* gluesBuild2DMipmapLevelsCore() */
1096
 
 
1097
 
GLint
1098
 
gluesBuild2DMipmapLevels(GLenum target, GLint internalFormat,
1099
 
                                           GLsizei width, GLsizei height, GLenum format,
1100
 
                                           GLenum type, GLint userLevel, GLint baseLevel,
1101
 
                                           GLint maxLevel, const void* data)
1102
 
{
1103
 
   int level, levels;
1104
 
 
1105
 
   int rc=checkMipmapArgs(internalFormat,format,type);
1106
 
 
1107
 
   if (rc!=0)
1108
 
   {
1109
 
          return rc;
1110
 
   }
1111
 
 
1112
 
   if (width<1 || height<1)
1113
 
   {
1114
 
          return GLUES_INVALID_VALUE;
1115
 
   }
1116
 
 
1117
 
   levels=computeLog(width);
1118
 
   level=computeLog(height);
1119
 
   if (level>levels)
1120
 
   {
1121
 
          levels=level;
1122
 
   }
1123
 
 
1124
 
   levels+=userLevel;
1125
 
   if (!isLegalLevels(userLevel, baseLevel, maxLevel, levels))
1126
 
   {
1127
 
          return GLUES_INVALID_VALUE;
1128
 
   }
1129
 
 
1130
 
   return gluesBuild2DMipmapLevelsCore(target, internalFormat, width, height,
1131
 
                                                                         width, height, format, type,
1132
 
                                                                         userLevel, baseLevel, maxLevel, data);
1133
 
} /* gluesBuild2DMipmapLevels() */
1134
 
 
1135
 
GLint gluesBuild2DMipmaps(GLenum target, GLint internalFormat, GLsizei width,
1136
 
                                  GLsizei height, GLenum format, GLenum type, const void* data)
1137
 
{
1138
 
   GLint widthPowerOf2, heightPowerOf2;
1139
 
   int level, levels;
1140
 
 
1141
 
   int rc=checkMipmapArgs(internalFormat,format,type);
1142
 
   if (rc!=0)
1143
 
   {
1144
 
          return rc;
1145
 
   }
1146
 
 
1147
 
   if (width<1 || height<1)
1148
 
   {
1149
 
          return GLUES_INVALID_VALUE;
1150
 
   }
1151
 
 
1152
 
   closestFit(target, width, height, internalFormat, format, type,
1153
 
                          &widthPowerOf2,&heightPowerOf2);
1154
 
 
1155
 
   levels=computeLog(widthPowerOf2);
1156
 
   level=computeLog(heightPowerOf2);
1157
 
   if (level>levels)
1158
 
   {
1159
 
          levels=level;
1160
 
   }
1161
 
 
1162
 
   return gluesBuild2DMipmapLevelsCore(target,internalFormat, width, height,
1163
 
                                                                         widthPowerOf2, heightPowerOf2, format,
1164
 
                                                                         type, 0, 0, levels, data);
1165
 
}  /* gluesBuild2DMipmaps() */
1166
 
 
1167
 
/*
1168
 
 * Utility Routines
1169
 
 */
1170
 
static GLint elements_per_group(GLenum format, GLenum type)
1171
 
{
1172
 
   /*
1173
 
        * Return the number of elements per group of a specified format
1174
 
        */
1175
 
 
1176
 
   /* If the type is packedpixels then answer is 1 (ignore format) */
1177
 
   if (type==GL_UNSIGNED_SHORT_5_6_5 ||
1178
 
           type==GL_UNSIGNED_SHORT_4_4_4_4 ||
1179
 
           type==GL_UNSIGNED_SHORT_5_5_5_1)
1180
 
   {
1181
 
          return 1;
1182
 
   }
1183
 
 
1184
 
   /* Types are not packed pixels, so get elements per group */
1185
 
   switch(format)
1186
 
   {
1187
 
          case GL_RGB:
1188
 
                   return 3;
1189
 
          case GL_LUMINANCE_ALPHA:
1190
 
                   return 2;
1191
 
          case GL_RGBA:
1192
 
                   return 4;
1193
 
          default:
1194
 
                   return 1;
1195
 
   }
1196
 
}
1197
 
 
1198
 
static GLfloat bytes_per_element(GLenum type)
1199
 
{
1200
 
   /*
1201
 
        * Return the number of bytes per element, based on the element type
1202
 
        */
1203
 
   switch(type)
1204
 
   {
1205
 
          case GL_UNSIGNED_BYTE:
1206
 
                   return(sizeof(GLubyte));
1207
 
          case GL_UNSIGNED_SHORT_5_6_5:
1208
 
          case GL_UNSIGNED_SHORT_4_4_4_4:
1209
 
          case GL_UNSIGNED_SHORT_5_5_5_1:
1210
 
                   return(sizeof(GLushort));
1211
 
          default:
1212
 
                   return 4;
1213
 
   }
1214
 
}
1215
 
 
1216
 
/*
1217
 
** Compute memory required for internal packed array of data of given type
1218
 
** and format.
1219
 
*/
1220
 
static GLint image_size(GLint width, GLint height, GLenum format, GLenum type)
1221
 
{
1222
 
   int bytes_per_row;
1223
 
   int components;
1224
 
 
1225
 
   assert(width>0);
1226
 
   assert(height>0);
1227
 
   components=elements_per_group(format, type);
1228
 
 
1229
 
   bytes_per_row=(int)(bytes_per_element(type)*width);
1230
 
 
1231
 
   return bytes_per_row*height*components;
1232
 
}
1233
 
 
1234
 
 
1235
 
/*--------------------------------------------------------------------------
1236
 
 * Decimation of packed pixel types
1237
 
 *--------------------------------------------------------------------------
1238
 
 */
1239
 
static void extract565(int isSwap, const void* packedPixel, GLfloat extractComponents[])
1240
 
{
1241
 
   GLushort ushort=*(const GLushort*)packedPixel;
1242
 
 
1243
 
   if (isSwap)
1244
 
   {
1245
 
          ushort=__GLUES_SWAP_2_BYTES(packedPixel);
1246
 
   }
1247
 
   else
1248
 
   {
1249
 
          ushort=*(const GLushort*)packedPixel;
1250
 
   }
1251
 
 
1252
 
   /* 11111000,00000000 == 0xf800 */
1253
 
   /* 00000111,11100000 == 0x07e0 */
1254
 
   /* 00000000,00011111 == 0x001f */
1255
 
 
1256
 
   extractComponents[0]=(float)((ushort&0xf800)>>11)/31.0f; /* 31 = 2^5-1*/
1257
 
   extractComponents[1]=(float)((ushort&0x07e0)>>5)/63.0f;  /* 63 = 2^6-1*/
1258
 
   extractComponents[2]=(float)((ushort&0x001f))/31.0f;
1259
 
} /* extract565() */
1260
 
 
1261
 
static void shove565(const GLfloat shoveComponents[], int index, void* packedPixel)
1262
 
{
1263
 
   /* 11111000,00000000 == 0xf800 */
1264
 
   /* 00000111,11100000 == 0x07e0 */
1265
 
   /* 00000000,00011111 == 0x001f */
1266
 
 
1267
 
   assert(0.0<=shoveComponents[0] && shoveComponents[0]<=1.0);
1268
 
   assert(0.0<=shoveComponents[1] && shoveComponents[1]<=1.0);
1269
 
   assert(0.0<=shoveComponents[2] && shoveComponents[2]<=1.0);
1270
 
 
1271
 
   /* due to limited precision, need to round before shoving */
1272
 
   ((GLushort*)packedPixel)[index]=((GLushort)((shoveComponents[0]*31)+0.5)<<11)&0xf800;
1273
 
   ((GLushort*)packedPixel)[index]|=((GLushort)((shoveComponents[1]*63)+0.5)<<5)&0x07e0;
1274
 
   ((GLushort*)packedPixel)[index]|=((GLushort)((shoveComponents[2]*31)+0.5))&0x001f;
1275
 
} /* shove565() */
1276
 
 
1277
 
static void extract4444(int isSwap,const void* packedPixel, GLfloat extractComponents[])
1278
 
{
1279
 
   GLushort ushort;
1280
 
 
1281
 
   if (isSwap)
1282
 
   {
1283
 
          ushort=__GLUES_SWAP_2_BYTES(packedPixel);
1284
 
   }
1285
 
   else
1286
 
   {
1287
 
          ushort=*(const GLushort*)packedPixel;
1288
 
   }
1289
 
 
1290
 
   /* 11110000,00000000 == 0xf000 */
1291
 
   /* 00001111,00000000 == 0x0f00 */
1292
 
   /* 00000000,11110000 == 0x00f0 */
1293
 
   /* 00000000,00001111 == 0x000f */
1294
 
 
1295
 
   extractComponents[0]=(float)((ushort&0xf000)>>12)/15.0f;/* 15=2^4-1 */
1296
 
   extractComponents[1]=(float)((ushort&0x0f00)>>8)/15.0f;
1297
 
   extractComponents[2]=(float)((ushort&0x00f0)>>4)/15.0f;
1298
 
   extractComponents[3]=(float)((ushort&0x000f))/15.0f;
1299
 
} /* extract4444() */
1300
 
 
1301
 
static void shove4444(const GLfloat shoveComponents[], int index,void* packedPixel)
1302
 
{
1303
 
   assert(0.0<=shoveComponents[0] && shoveComponents[0]<=1.0);
1304
 
   assert(0.0<=shoveComponents[1] && shoveComponents[1]<=1.0);
1305
 
   assert(0.0<=shoveComponents[2] && shoveComponents[2]<=1.0);
1306
 
   assert(0.0<=shoveComponents[3] && shoveComponents[3]<=1.0);
1307
 
 
1308
 
   /* due to limited precision, need to round before shoving */
1309
 
   ((GLushort*)packedPixel)[index]=((GLushort)((shoveComponents[0]*15)+0.5)<<12)&0xf000;
1310
 
   ((GLushort*)packedPixel)[index]|=((GLushort)((shoveComponents[1]*15)+0.5)<<8)&0x0f00;
1311
 
   ((GLushort*)packedPixel)[index]|=((GLushort)((shoveComponents[2]*15)+0.5)<<4)&0x00f0;
1312
 
   ((GLushort*)packedPixel)[index]|=((GLushort)((shoveComponents[3]*15)+0.5))&0x000f;
1313
 
} /* shove4444() */
1314
 
 
1315
 
static void extract5551(int isSwap,const void* packedPixel, GLfloat extractComponents[])
1316
 
{
1317
 
   GLushort ushort;
1318
 
 
1319
 
   if (isSwap)
1320
 
   {
1321
 
          ushort=__GLUES_SWAP_2_BYTES(packedPixel);
1322
 
   }
1323
 
   else
1324
 
   {
1325
 
          ushort=*(const GLushort*)packedPixel;
1326
 
   }
1327
 
 
1328
 
   /* 11111000,00000000 == 0xf800 */
1329
 
   /* 00000111,11000000 == 0x07c0 */
1330
 
   /* 00000000,00111110 == 0x003e */
1331
 
   /* 00000000,00000001 == 0x0001 */
1332
 
 
1333
 
   extractComponents[0]=(float)((ushort&0xf800)>>11)/31.0f;/* 31 = 2^5-1*/
1334
 
   extractComponents[1]=(float)((ushort&0x07c0)>>6)/31.0f;
1335
 
   extractComponents[2]=(float)((ushort&0x003e)>>1)/31.0f;
1336
 
   extractComponents[3]=(float)((ushort&0x0001));
1337
 
} /* extract5551() */
1338
 
 
1339
 
static void shove5551(const GLfloat shoveComponents[], int index,void* packedPixel)
1340
 
{
1341
 
   /* 11111000,00000000 == 0xf800 */
1342
 
   /* 00000111,11000000 == 0x07c0 */
1343
 
   /* 00000000,00111110 == 0x003e */
1344
 
   /* 00000000,00000001 == 0x0001 */
1345
 
 
1346
 
   assert(0.0<=shoveComponents[0] && shoveComponents[0]<=1.0);
1347
 
   assert(0.0<=shoveComponents[1] && shoveComponents[1]<=1.0);
1348
 
   assert(0.0<=shoveComponents[2] && shoveComponents[2]<=1.0);
1349
 
   assert(0.0<=shoveComponents[3] && shoveComponents[3]<=1.0);
1350
 
 
1351
 
   /* due to limited precision, need to round before shoving */
1352
 
   ((GLushort*)packedPixel)[index]=((GLushort)((shoveComponents[0]*31)+0.5)<<11)&0xf800;
1353
 
   ((GLushort*)packedPixel)[index]|=((GLushort)((shoveComponents[1]*31)+0.5)<<6)&0x07c0;
1354
 
   ((GLushort*)packedPixel)[index]|=((GLushort)((shoveComponents[2]*31)+0.5)<<1)&0x003e;
1355
 
   ((GLushort*)packedPixel)[index]|=((GLushort)((shoveComponents[3])+0.5))&0x0001;
1356
 
} /* shove5551() */
1357
 
 
1358
 
static void scaleInternalPackedPixel(int components,
1359
 
                                                                         void (*extractPackedPixel)
1360
 
                                                                         (int, const void*,GLfloat []),
1361
 
                                                                         void (*shovePackedPixel)
1362
 
                                                                         (const GLfloat [], int, void*),
1363
 
                                                                         GLint widthIn,GLint heightIn,
1364
 
                                                                         const void* dataIn,
1365
 
                                                                         GLint widthOut,GLint heightOut,
1366
 
                                                                         void* dataOut,
1367
 
                                                                         GLint pixelSizeInBytes,
1368
 
                                                                         GLint rowSizeInBytes, GLint isSwap)
1369
 
{
1370
 
   float convx;
1371
 
   float convy;
1372
 
   float percent;
1373
 
 
1374
 
   /* Max components in a format is 4, so... */
1375
 
   float totals[4];
1376
 
   float extractTotals[4], extractMoreTotals[4], shoveTotals[4];
1377
 
 
1378
 
   float area;
1379
 
   int i,j,k,xindex;
1380
 
 
1381
 
   const char *temp, *temp0;
1382
 
   int outindex;
1383
 
 
1384
 
   int lowx_int, highx_int, lowy_int, highy_int;
1385
 
   float x_percent, y_percent;
1386
 
   float lowx_float, highx_float, lowy_float, highy_float;
1387
 
   float convy_float, convx_float;
1388
 
   int convy_int, convx_int;
1389
 
   int l, m;
1390
 
   const char* left;
1391
 
   const char* right;
1392
 
 
1393
 
   if (widthIn==widthOut*2 && heightIn==heightOut*2)
1394
 
   {
1395
 
          halveImagePackedPixel(components,extractPackedPixel,shovePackedPixel,
1396
 
                                                        widthIn, heightIn, dataIn, dataOut,
1397
 
                                                        pixelSizeInBytes,rowSizeInBytes,isSwap);
1398
 
          return;
1399
 
   }
1400
 
   convy=(float)heightIn/heightOut;
1401
 
   convx=(float)widthIn/widthOut;
1402
 
   convy_int=(int)floor(convy);
1403
 
   convy_float=convy-convy_int;
1404
 
   convx_int=(int)floor(convx);
1405
 
   convx_float=convx-convx_int;
1406
 
 
1407
 
   area=convx*convy;
1408
 
 
1409
 
   lowy_int=0;
1410
 
   lowy_float=0;
1411
 
   highy_int=convy_int;
1412
 
   highy_float=convy_float;
1413
 
 
1414
 
   for (i=0; i<heightOut; i++)
1415
 
   {
1416
 
          lowx_int=0;
1417
 
          lowx_float=0;
1418
 
          highx_int=convx_int;
1419
 
          highx_float=convx_float;
1420
 
 
1421
 
          for (j=0; j<widthOut; j++)
1422
 
          {
1423
 
                 /*
1424
 
                 ** Ok, now apply box filter to box that goes from (lowx, lowy)
1425
 
                 ** to (highx, highy) on input data into this pixel on output
1426
 
                 ** data.
1427
 
                 */
1428
 
                 totals[0]=totals[1]=totals[2]=totals[3]=0.0;
1429
 
 
1430
 
                 /* calculate the value for pixels in the 1st row */
1431
 
                 xindex=lowx_int*pixelSizeInBytes;
1432
 
                 if ((highy_int>lowy_int) && (highx_int>lowx_int))
1433
 
                 {
1434
 
                        y_percent=1-lowy_float;
1435
 
                        temp=(const char*)dataIn+xindex+lowy_int*rowSizeInBytes;
1436
 
                        percent=y_percent*(1-lowx_float);
1437
 
                        (*extractPackedPixel)(isSwap, temp, extractTotals);
1438
 
                        for (k=0; k<components; k++)
1439
 
                        {
1440
 
                           totals[k]+=extractTotals[k]*percent;
1441
 
                        }
1442
 
                        left=temp;
1443
 
                        for (l=lowx_int+1; l<highx_int; l++)
1444
 
                        {
1445
 
                           temp+=pixelSizeInBytes;
1446
 
                           (*extractPackedPixel)(isSwap, temp, extractTotals);
1447
 
                           for (k=0; k<components; k++)
1448
 
                           {
1449
 
                                  totals[k]+=extractTotals[k]*y_percent;
1450
 
                           }
1451
 
                        }
1452
 
                        temp+=pixelSizeInBytes;
1453
 
                        right=temp;
1454
 
                        percent=y_percent*highx_float;
1455
 
                        (*extractPackedPixel)(isSwap, temp, extractTotals);
1456
 
                        for (k=0; k<components; k++)
1457
 
                        {
1458
 
                           totals[k]+=extractTotals[k]*percent;
1459
 
                        }
1460
 
 
1461
 
                        /* calculate the value for pixels in the last row */
1462
 
                        y_percent=highy_float;
1463
 
                        percent=y_percent*(1-lowx_float);
1464
 
                        temp=(const char*)dataIn+xindex+highy_int*rowSizeInBytes;
1465
 
                        (*extractPackedPixel)(isSwap, temp, extractTotals);
1466
 
                        for (k=0; k<components; k++)
1467
 
                        {
1468
 
                           totals[k]+=extractTotals[k]*percent;
1469
 
                        }
1470
 
                        for (l=lowx_int+1; l<highx_int; l++)
1471
 
                        {
1472
 
                           temp+=pixelSizeInBytes;
1473
 
                           (*extractPackedPixel)(isSwap, temp, extractTotals);
1474
 
                           for (k=0; k<components; k++)
1475
 
                           {
1476
 
                                  totals[k]+=extractTotals[k]*y_percent;
1477
 
                           }
1478
 
                        }
1479
 
                        temp+=pixelSizeInBytes;
1480
 
                        percent=y_percent*highx_float;
1481
 
                        (*extractPackedPixel)(isSwap, temp, extractTotals);
1482
 
                        for (k=0; k<components; k++)
1483
 
                        {
1484
 
                           totals[k]+=extractTotals[k]*percent;
1485
 
                        }
1486
 
 
1487
 
                        /* calculate the value for pixels in the 1st and last column */
1488
 
                        for (m=lowy_int+1; m<highy_int; m++)
1489
 
                        {
1490
 
                           left+=rowSizeInBytes;
1491
 
                           right+=rowSizeInBytes;
1492
 
                           (*extractPackedPixel)(isSwap, left, extractTotals);
1493
 
                           (*extractPackedPixel)(isSwap, right, extractMoreTotals);
1494
 
                           for (k=0; k<components; k++)
1495
 
                           {
1496
 
                                  totals[k]+=(extractTotals[k]*(1-lowx_float)+extractMoreTotals[k]*highx_float);
1497
 
                           }
1498
 
                        }
1499
 
                 }
1500
 
                 else
1501
 
                 {
1502
 
                        if (highy_int>lowy_int)
1503
 
                        {
1504
 
                           x_percent=highx_float-lowx_float;
1505
 
                           percent=(1-lowy_float)*x_percent;
1506
 
                           temp=(const char*)dataIn+xindex+lowy_int*rowSizeInBytes;
1507
 
                           (*extractPackedPixel)(isSwap, temp, extractTotals);
1508
 
                           for (k=0; k<components; k++)
1509
 
                           {
1510
 
                                  totals[k]+=extractTotals[k]*percent;
1511
 
                           }
1512
 
                           for (m=lowy_int+1; m<highy_int; m++)
1513
 
                           {
1514
 
                                  temp+=rowSizeInBytes;
1515
 
                                  (*extractPackedPixel)(isSwap, temp, extractTotals);
1516
 
                                  for (k=0; k<components; k++)
1517
 
                                  {
1518
 
                                         totals[k]+=extractTotals[k]*x_percent;
1519
 
                                  }
1520
 
                           }
1521
 
                           percent=x_percent*highy_float;
1522
 
                           temp+=rowSizeInBytes;
1523
 
                           (*extractPackedPixel)(isSwap, temp, extractTotals);
1524
 
                           for (k=0; k<components; k++)
1525
 
                           {
1526
 
                                  totals[k]+=extractTotals[k]*percent;
1527
 
                           }
1528
 
                        }
1529
 
                        else
1530
 
                        {
1531
 
                           if (highx_int > lowx_int)
1532
 
                           {
1533
 
                                  y_percent=highy_float-lowy_float;
1534
 
                                  percent=(1-lowx_float)*y_percent;
1535
 
                                  temp=(const char*)dataIn+xindex+lowy_int*rowSizeInBytes;
1536
 
                                  (*extractPackedPixel)(isSwap, temp, extractTotals);
1537
 
                                  for (k=0; k<components; k++)
1538
 
                                  {
1539
 
                                         totals[k]+= extractTotals[k] * percent;
1540
 
                                  }
1541
 
                                  for (l=lowx_int+1; l<highx_int; l++)
1542
 
                                  {
1543
 
                                         temp+=pixelSizeInBytes;
1544
 
                                         (*extractPackedPixel)(isSwap, temp, extractTotals);
1545
 
                                         for (k=0; k<components; k++)
1546
 
                                         {
1547
 
                                                totals[k]+=extractTotals[k]*y_percent;
1548
 
                                         }
1549
 
                                  }
1550
 
                                  temp+=pixelSizeInBytes;
1551
 
                                  percent=y_percent*highx_float;
1552
 
                                  (*extractPackedPixel)(isSwap, temp, extractTotals);
1553
 
                                  for (k=0; k<components; k++)
1554
 
                                  {
1555
 
                                         totals[k]+=extractTotals[k]*percent;
1556
 
                                  }
1557
 
                           }
1558
 
                           else
1559
 
                           {
1560
 
                                  percent=(highy_float-lowy_float)*(highx_float-lowx_float);
1561
 
                                  temp=(const char*)dataIn+xindex+lowy_int*rowSizeInBytes;
1562
 
                                  (*extractPackedPixel)(isSwap, temp, extractTotals);
1563
 
                                  for (k=0; k<components; k++)
1564
 
                                  {
1565
 
                                         totals[k]+=extractTotals[k]*percent;
1566
 
                                  }
1567
 
                           }
1568
 
                        }
1569
 
                 }
1570
 
 
1571
 
                 /* this is for the pixels in the body */
1572
 
                 temp0=(const char*)dataIn+xindex+pixelSizeInBytes+(lowy_int+1)*rowSizeInBytes;
1573
 
                 for (m=lowy_int+1; m<highy_int; m++)
1574
 
                 {
1575
 
                        temp=temp0;
1576
 
                        for (l=lowx_int+1; l<highx_int; l++)
1577
 
                        {
1578
 
                           (*extractPackedPixel)(isSwap, temp, extractTotals);
1579
 
                           for (k=0; k<components; k++)
1580
 
                           {
1581
 
                                  totals[k]+=extractTotals[k];
1582
 
                           }
1583
 
                           temp+=pixelSizeInBytes;
1584
 
                        }
1585
 
                        temp0 += rowSizeInBytes;
1586
 
                 }
1587
 
 
1588
 
                 outindex=(j+(i*widthOut));
1589
 
                 for (k=0; k<components; k++)
1590
 
                 {
1591
 
                        shoveTotals[k]=totals[k]/area;
1592
 
                 }
1593
 
                 (*shovePackedPixel)(shoveTotals, outindex, (void*)dataOut);
1594
 
                 lowx_int=highx_int;
1595
 
                 lowx_float=highx_float;
1596
 
                 highx_int+=convx_int;
1597
 
                 highx_float+=convx_float;
1598
 
                 if (highx_float>1)
1599
 
                 {
1600
 
                        highx_float-=1.0;
1601
 
                        highx_int++;
1602
 
                 }
1603
 
          }
1604
 
          lowy_int=highy_int;
1605
 
          lowy_float=highy_float;
1606
 
          highy_int+=convy_int;
1607
 
          highy_float+=convy_float;
1608
 
 
1609
 
          if (highy_float>1)
1610
 
          {
1611
 
                 highy_float-=1.0;
1612
 
                 highy_int++;
1613
 
          }
1614
 
   }
1615
 
 
1616
 
   assert(outindex==(widthOut*heightOut-1));
1617
 
} /* scaleInternalPackedPixel() */
1618
 
 
1619
 
/* rowSizeInBytes is at least the width (in bytes) due to padding on
1620
 
 *  inputs; not always equal. Output NEVER has row padding.
1621
 
 */
1622
 
static void halveImagePackedPixel(int components,
1623
 
                                                                  void (*extractPackedPixel)
1624
 
                                                                  (int, const void*,GLfloat []),
1625
 
                                                                  void (*shovePackedPixel)
1626
 
                                                                  (const GLfloat [],int, void*),
1627
 
                                                                  GLint width, GLint height,
1628
 
                                                                  const void* dataIn, void* dataOut,
1629
 
                                                                  GLint pixelSizeInBytes,
1630
 
                                                                  GLint rowSizeInBytes, GLint isSwap)
1631
 
{
1632
 
   /* handle case where there is only 1 column/row */
1633
 
   if (width==1 || height==1)
1634
 
   {
1635
 
          assert(!(width==1 && height==1)); /* can't be 1x1 */
1636
 
          halve1DimagePackedPixel(components,extractPackedPixel,shovePackedPixel,
1637
 
                                                          width,height,dataIn,dataOut,pixelSizeInBytes,
1638
 
                                                          rowSizeInBytes,isSwap);
1639
 
          return;
1640
 
   }
1641
 
 
1642
 
   {
1643
 
          int ii, jj;
1644
 
 
1645
 
          int halfWidth=width/2;
1646
 
          int halfHeight=height/2;
1647
 
          const char* src=(const char*)dataIn;
1648
 
          int padBytes=rowSizeInBytes-(width*pixelSizeInBytes);
1649
 
          int outIndex=0;
1650
 
 
1651
 
          for (ii=0; ii<halfHeight; ii++)
1652
 
          {
1653
 
                 for (jj=0; jj<halfWidth; jj++)
1654
 
                 {
1655
 
#define BOX4 4
1656
 
                        float totals[4];              /* 4 is maximum components */
1657
 
                        float extractTotals[BOX4][4]; /* 4 is maximum components */
1658
 
                        int cc;
1659
 
 
1660
 
                        (*extractPackedPixel)(isSwap, src, &extractTotals[0][0]);
1661
 
                        (*extractPackedPixel)(isSwap, (src+pixelSizeInBytes), &extractTotals[1][0]);
1662
 
                        (*extractPackedPixel)(isSwap, (src+rowSizeInBytes), &extractTotals[2][0]);
1663
 
                        (*extractPackedPixel)(isSwap, (src+rowSizeInBytes+pixelSizeInBytes), &extractTotals[3][0]);
1664
 
                        for (cc=0; cc<components; cc++)
1665
 
                        {
1666
 
                           int kk;
1667
 
 
1668
 
                           /* grab 4 pixels to average */
1669
 
                           totals[cc]=0.0;
1670
 
                           for (kk=0; kk<BOX4; kk++)
1671
 
                           {
1672
 
                                  totals[cc]+=extractTotals[kk][cc];
1673
 
                           }
1674
 
                           totals[cc]/=(float)BOX4;
1675
 
                        }
1676
 
                        (*shovePackedPixel)(totals, outIndex, dataOut);
1677
 
 
1678
 
                        outIndex++;
1679
 
                        /* skip over to next square of 4 */
1680
 
                        src+=pixelSizeInBytes+pixelSizeInBytes;
1681
 
                 }
1682
 
                 /* skip past pad bytes, if any, to get to next row */
1683
 
                 src+=padBytes;
1684
 
 
1685
 
                 /* src is at beginning of a row here, but it's the second row of
1686
 
                  * the square block of 4 pixels that we just worked on so we
1687
 
                  * need to go one more row.
1688
 
                  * i.e.,
1689
 
                  *                   OO...
1690
 
                  *           here -->OO...
1691
 
                  *       but want -->OO...
1692
 
                  *                   OO...
1693
 
                  *                   ...
1694
 
                  */
1695
 
                 src+=rowSizeInBytes;
1696
 
          }
1697
 
 
1698
 
          /* both pointers must reach one byte after the end */
1699
 
          assert(src==&((const char*)dataIn)[rowSizeInBytes*height]);
1700
 
          assert(outIndex==halfWidth*halfHeight);
1701
 
   }
1702
 
} /* halveImagePackedPixel() */
1703
 
 
1704
 
static void halve1DimagePackedPixel(int components,
1705
 
                                                                        void (*extractPackedPixel)
1706
 
                                                                        (int, const void*,GLfloat []),
1707
 
                                                                        void (*shovePackedPixel)
1708
 
                                                                        (const GLfloat [],int, void*),
1709
 
                                                                        GLint width, GLint height,
1710
 
                                                                        const void* dataIn, void* dataOut,
1711
 
                                                                        GLint pixelSizeInBytes,
1712
 
                                                                        GLint rowSizeInBytes, GLint isSwap)
1713
 
{
1714
 
   int halfWidth=width/2;
1715
 
   int halfHeight=height/2;
1716
 
   const char *src=(const char*)dataIn;
1717
 
   int jj;
1718
 
 
1719
 
   assert(width==1 || height==1); /* must be 1D */
1720
 
   assert(width!= height);        /* can't be square */
1721
 
 
1722
 
   if (height==1)
1723
 
   {
1724
 
          /* 1 row */
1725
 
          int outIndex=0;
1726
 
 
1727
 
          assert(width!=1);           /* widthxheight can't be 1x1 */
1728
 
          halfHeight=1;
1729
 
 
1730
 
          /* one horizontal row with possible pad bytes */
1731
 
          for (jj=0; jj<halfWidth; jj++)
1732
 
          {
1733
 
#define BOX2 2
1734
 
                 float totals[4];               /* 4 is maximum components */
1735
 
                 float extractTotals[BOX2][4];  /* 4 is maximum components */
1736
 
                 int cc;
1737
 
 
1738
 
                 /* average two at a time, instead of four */
1739
 
                 (*extractPackedPixel)(isSwap, src, &extractTotals[0][0]);
1740
 
                 (*extractPackedPixel)(isSwap, (src+pixelSizeInBytes), &extractTotals[1][0]);
1741
 
                 for (cc=0; cc<components; cc++)
1742
 
                 {
1743
 
                        int kk;
1744
 
 
1745
 
                        /* grab 2 pixels to average */
1746
 
                        totals[cc]=0.0;
1747
 
                        for (kk=0; kk<BOX2; kk++)
1748
 
                        {
1749
 
                           totals[cc]+=extractTotals[kk][cc];
1750
 
                        }
1751
 
                        totals[cc]/=(float)BOX2;
1752
 
                 }
1753
 
                 (*shovePackedPixel)(totals, outIndex, dataOut);
1754
 
 
1755
 
                 outIndex++;
1756
 
                 /* skip over to next group of 2 */
1757
 
                 src+= pixelSizeInBytes + pixelSizeInBytes;
1758
 
          }
1759
 
 
1760
 
          {
1761
 
                 int padBytes=rowSizeInBytes-(width*pixelSizeInBytes);
1762
 
                 src+=padBytes;                 /* for assertion only */
1763
 
          }
1764
 
          assert(src==&((const char*)dataIn)[rowSizeInBytes]);
1765
 
          assert(outIndex==halfWidth*halfHeight);
1766
 
   }
1767
 
   else
1768
 
   {
1769
 
          if (width==1)             /* 1 column */
1770
 
          {
1771
 
                 int outIndex=0;
1772
 
 
1773
 
                 assert(height!=1);        /* widthxheight can't be 1x1 */
1774
 
                 halfWidth=1;
1775
 
                 /* one vertical column with possible pad bytes per row */
1776
 
                 /* average two at a time */
1777
 
 
1778
 
                 for (jj=0; jj<halfHeight; jj++)
1779
 
                 {
1780
 
#define BOX2 2
1781
 
                        float totals[4];               /* 4 is maximum components */
1782
 
                        float extractTotals[BOX2][4];  /* 4 is maximum components */
1783
 
                        int cc;
1784
 
 
1785
 
                        /* average two at a time, instead of four */
1786
 
                        (*extractPackedPixel)(isSwap, src, &extractTotals[0][0]);
1787
 
                        (*extractPackedPixel)(isSwap, (src+rowSizeInBytes), &extractTotals[1][0]);
1788
 
                        for (cc=0; cc<components; cc++)
1789
 
                        {
1790
 
                           int kk;
1791
 
 
1792
 
                           /* grab 2 pixels to average */
1793
 
                           totals[cc]=0.0;
1794
 
                           for (kk=0; kk<BOX2; kk++)
1795
 
                           {
1796
 
                                  totals[cc]+=extractTotals[kk][cc];
1797
 
                           }
1798
 
                           totals[cc]/=(float)BOX2;
1799
 
                        }
1800
 
                        (*shovePackedPixel)(totals, outIndex, dataOut);
1801
 
 
1802
 
                        outIndex++;
1803
 
                        src+=rowSizeInBytes+rowSizeInBytes; /* go to row after next */
1804
 
                 }
1805
 
 
1806
 
                 assert(src==&((const char*)dataIn)[rowSizeInBytes*height]);
1807
 
                 assert(outIndex==halfWidth*halfHeight);
1808
 
          }
1809
 
   }
1810
 
} /* halve1DimagePackedPixel() */
1811
 
 
1812
 
/*===========================================================================*/