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