home *** CD-ROM | disk | FTP | other *** search
/ Aminet 10 / aminetcdnumber101996.iso / Aminet / gfx / x11 / Mesa_Amiwin.lha / Mesa-Amiwin / src-glu / mipmap.c < prev    next >
C/C++ Source or Header  |  1995-11-17  |  18KB  |  728 lines

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