home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / mesa5.zip / mesa5src.zip / MesaDLL / mipmap.cpp < prev    next >
C/C++ Source or Header  |  2002-12-21  |  20KB  |  826 lines

  1. /* $Id: mipmap.c,v 1.8 2000/10/26 21:48:18 brianp Exp $ */
  2. /* src-glu */
  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. }
  826.