home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 6 / AACD06.ISO / AACD / System / Mesa-3.1 / src-glu / mipmap.c < prev    next >
C/C++ Source or Header  |  2000-01-05  |  21KB  |  836 lines

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