[gimp-dds] / tags / release-1.2.1 / dxt.c Repository:
ViewVC logotype

View of /tags/release-1.2.1/dxt.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 56 - (download) (as text) (annotate)
Wed Jan 31 18:56:21 2007 UTC (2 years, 9 months ago) by cocidius
File size: 36333 byte(s)
1.2.1 release
    1 /*
    2    DDS GIMP plugin
    3 
    4    Copyright (C) 2004 Shawn Kirst <skirst@fuse.net>,
    5    with parts (C) 2003 Arne Reuter <homepage@arnereuter.de> where specified.
    6 
    7    This program is free software; you can redistribute it and/or
    8    modify it under the terms of the GNU General Public
    9    License as published by the Free Software Foundation; either
   10    version 2 of the License, or (at your option) any later version.
   11 
   12    This program is distributed in the hope that it will be useful,
   13    but WITHOUT ANY WARRANTY; without even the implied warranty of
   14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   15    General Public License for more details.
   16 
   17    You should have received a copy of the GNU General Public License
   18    along with this program; see the file COPYING.  If not, write to
   19    the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
   20    Boston, MA 02111-1307, USA.
   21 */
   22 
   23 #ifdef WIN32
   24 #include <windows.h>
   25 #else
   26 #include <dlfcn.h>
   27 #endif
   28 #include <string.h>
   29 #include <math.h>
   30 #include <GL/glew.h>
   31 #include <GL/glut.h>
   32 #include <glib.h>
   33 
   34 
   35 #include "dds.h"
   36 #include "endian.h"
   37 
   38 #define IS_POT(x)      (!((x) & ((x) - 1)))
   39 #define LERP(a, b, t)  ((a) + ((b) - (a)) * (t))
   40 
   41 static int generate_mipmaps_software(unsigned char *dst, unsigned char *src,
   42                                      unsigned int width, unsigned int height,
   43                                      int bpp, int indexed, int mipmaps);
   44 
   45 #ifdef USE_SOFTWARE_COMPRESSION
   46 #ifdef WIN32
   47 HANDLE hdxtn = NULL;
   48 #define DXTN_DLL "dxtn.dll"
   49 #define dlopen(handle, flags)  LoadLibrary(handle)
   50 #define dlsym(handle, symbol)  GetProcAddress(handle, symbol)
   51 #define dlclose(handle)        FreeLibrary(handle)
   52 #define RTLD_LAZY   0
   53 #define RTLD_GLOBAL 0
   54 #else
   55 void *hdxtn = NULL;
   56 #define DXTN_DLL "libtxc_dxtn.so"
   57 #endif
   58 static void (*compress_dxtn)(int, int, int, const unsigned char*, int, unsigned char *) = NULL;
   59 #endif // #ifdef USE_SOFTWARE_COMPRESSION
   60 
   61 char *initialize_opengl(void)
   62 {
   63    int argc = 1, err;
   64    char *argv[] = { "dds" };
   65 
   66    glutInit(&argc, argv);
   67    glutInitDisplayMode(GLUT_RGBA);
   68    glutInitWindowSize(1, 1);
   69    glutCreateWindow("GIMP DDS");
   70 
   71    err = glewInit();
   72    if(err != GLEW_OK)
   73       return((char*)glewGetErrorString(err));
   74 
   75 #ifndef USE_SOFTWARE_COMPRESSION
   76    if(!GLEW_ARB_texture_compression)
   77       return("GL_ARB_texture_compression is not supported by your OpenGL "
   78              "implementation.\n");
   79    if(!GLEW_S3_s3tc && !GLEW_EXT_texture_compression_s3tc)
   80       return("GL_S3_s3tc or GL_EXT_texture_compression_s3tc is not supported "
   81              "by your OpenGL implementation.\n");
   82 
   83    glHint(GL_TEXTURE_COMPRESSION_HINT_ARB, GL_NICEST);
   84 #else
   85    hdxtn = dlopen(DXTN_DLL, RTLD_LAZY | RTLD_GLOBAL);
   86    if(hdxtn == NULL)
   87       return("Unable to load library " DXTN_DLL);
   88    compress_dxtn = (void*)dlsym(hdxtn, "tx_compress_dxtn");
   89    if(compress_dxtn == NULL)
   90    {
   91       dlclose(hdxtn);
   92       return("Missing symbol `tx_compress_dxtn' in " DXTN_DLL);
   93    }
   94 #endif
   95 
   96    glPixelStorei(GL_PACK_ALIGNMENT, 1);
   97    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
   98 
   99    if(GLEW_SGIS_generate_mipmap)
  100       glHint(GL_GENERATE_MIPMAP_HINT_SGIS, GL_NICEST);
  101 
  102    return(0);
  103 }
  104 
  105 int get_num_mipmaps(int width, int height)
  106 {
  107    int w = width << 1;
  108    int h = height << 1;
  109    int n = 0;
  110 
  111    while(w != 1 || h != 1)
  112    {
  113       if(w > 1) w >>= 1;
  114       if(h > 1) h >>= 1;
  115       ++n;
  116    }
  117 
  118    return(n);
  119 }
  120 
  121 unsigned int get_mipmapped_size(int width, int height, int bpp,
  122                                 int level, int num, int format)
  123 {
  124    int w, h, n = 0;
  125    unsigned int size = 0;
  126 
  127    w = width >> level;
  128    h = height >> level;
  129    if(w == 0) w = 1;
  130    if(h == 0) h = 1;
  131    w <<= 1;
  132    h <<= 1;
  133 
  134    while(n < num && (w != 1 || h != 1))
  135    {
  136       if(w > 1) w >>= 1;
  137       if(h > 1) h >>= 1;
  138       if(format == DDS_COMPRESS_NONE)
  139          size += (w * h);
  140       else
  141          size += ((w + 3) >> 2) * ((h + 3) >> 2);
  142       ++n;
  143    }
  144 
  145    if(format == DDS_COMPRESS_NONE)
  146       size *= bpp;
  147    else
  148    {
  149       if(format == DDS_COMPRESS_DXT1 || format == DDS_COMPRESS_ATI1)
  150          size *= 8;
  151       else
  152          size *= 16;
  153    }
  154 
  155    return(size);
  156 }
  157 
  158 unsigned int get_volume_mipmapped_size(int width, int height,
  159                                        int depth, int bpp, int level,
  160                                        int num, int format)
  161 {
  162    int w, h, d, n = 0;
  163    unsigned int size = 0;
  164 
  165    w = width >> level;
  166    h = height >> level;
  167    d = depth >> level;
  168    if(w == 0) w = 1;
  169    if(h == 0) h = 1;
  170    if(d == 0) d = 1;
  171    w <<= 1;
  172    h <<= 1;
  173    d <<= 1;
  174 
  175    while(n < num && (w != 1 || h != 1))
  176    {
  177       if(w > 1) w >>= 1;
  178       if(h > 1) h >>= 1;
  179       if(d > 1) d >>= 1;
  180       if(format == DDS_COMPRESS_NONE)
  181          size += (w * h * d);
  182       else
  183          size += (((w + 3) >> 2) * ((h + 3) >> 2) * d);
  184       ++n;
  185    }
  186 
  187    if(format == DDS_COMPRESS_NONE)
  188       size *= bpp;
  189    else
  190    {
  191       if(format == DDS_COMPRESS_DXT1 || format == DDS_COMPRESS_ATI1)
  192          size *= 8;
  193       else
  194          size *= 16;
  195    }
  196 
  197    return(size);
  198 }
  199 
  200 static void compress_3dc(unsigned char *dst, unsigned char *src,
  201                          int width, int height, int bpp, int mipmaps,
  202                          int format)
  203 {
  204    int i, j, w, h;
  205    unsigned int offset, size;
  206    unsigned char *s1, *s2, *d1, *d2, *dtmp, *stmp;
  207 
  208 #ifdef USE_SOFTWARE_COMPRESSION
  209 
  210    if(format == DDS_COMPRESS_ATI1)
  211    {
  212       size = get_mipmapped_size(width, height, 4, 0, mipmaps, DDS_COMPRESS_NONE);
  213       stmp = g_malloc(size);
  214       memset(stmp, 0, size);
  215 
  216       for(i = j = 0; j < size; i += bpp, j += 4)
  217          stmp[j + 3] = src[i];
  218 
  219       size = get_mipmapped_size(width, height, 0, 0, mipmaps, DDS_COMPRESS_DXT5);
  220       dtmp = g_malloc(size);
  221 
  222       offset = 0;
  223       w = width;
  224       h = height;
  225       s1 = stmp;
  226 
  227       for(i = 0; i < mipmaps; ++i)
  228       {
  229          compress_dxtn(4, w, h, s1, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT,
  230                        dtmp + offset);
  231          s1 += (w * h * 4);
  232          offset += get_mipmapped_size(w, h, 0, 0, 1, DDS_COMPRESS_DXT5);
  233          if(w > 1) w >>= 1;
  234          if(h > 1) h >>= 1;
  235       }
  236 
  237       for(i = j = 0; i < size; i += 16, j += 8)
  238          memcpy(dst + j, dtmp + i, 8);
  239 
  240       g_free(dtmp);
  241       g_free(stmp);
  242    }
  243    else if(format == DDS_COMPRESS_ATI2)
  244    {
  245       size = get_mipmapped_size(width, height, 4, 0, mipmaps, DDS_COMPRESS_NONE);
  246       stmp = g_malloc(size * 2);
  247       memset(stmp, 0, size * 2);
  248 
  249       s1 = stmp;
  250       s2 = stmp + size;
  251 
  252       for(i = j = 0; j < size; i += bpp, j += 4)
  253       {
  254          s1[j + 3] = src[i + 1];
  255          s2[j + 3] = src[i];
  256       }
  257 
  258       size = get_mipmapped_size(width, height, 0, 0, mipmaps, DDS_COMPRESS_DXT5);
  259       dtmp = g_malloc(size * 2);
  260 
  261       d1 = dtmp;
  262       d2 = dtmp + size;
  263 
  264       offset = 0;
  265       w = width;
  266       h = height;
  267 
  268       for(i = 0; i < mipmaps; ++i)
  269       {
  270          compress_dxtn(4, w, h, s1, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, d1 + offset);
  271          compress_dxtn(4, w, h, s2, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, d2 + offset);
  272          s1 += (w * h * 4);
  273          s2 += (w * h * 4);
  274          offset += get_mipmapped_size(w, h, 0, 0, 1, DDS_COMPRESS_DXT5);
  275          if(w > 1) w >>= 1;
  276          if(h > 1) h >>= 1;
  277       }
  278 
  279       for(i = 0; i < size; i += 16)
  280       {
  281          memcpy(dst + i + 0, d1 + i, 8);
  282          memcpy(dst + i + 8, d2 + i, 8);
  283       }
  284 
  285       g_free(dtmp);
  286       g_free(stmp);
  287    }
  288 
  289 #else // #ifdef USE_SOFTWARE_COMPRESSION
  290 
  291    if(GLEW_SGIS_generate_mipmap)
  292       glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP_SGIS, GL_FALSE);
  293 
  294    if(format == DDS_COMPRESS_ATI1)
  295    {
  296       size = get_mipmapped_size(width, height, 4, 0, mipmaps, DDS_COMPRESS_NONE);
  297       stmp = g_malloc(size);
  298       memset(stmp, 0, size);
  299 
  300       for(i = j = 0; j < size; i += bpp, j += 4)
  301          stmp[j + 3] = src[i];
  302 
  303       size = get_mipmapped_size(width, height, 0, 0, mipmaps, DDS_COMPRESS_DXT5);
  304       dtmp = g_malloc(size);
  305 
  306       offset = 0;
  307       w = width;
  308       h = height;
  309       s1 = stmp;
  310 
  311       for(i = 0; i < mipmaps; ++i)
  312       {
  313          glTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT,
  314                       w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, s1);
  315          glGetCompressedTexImageARB(GL_TEXTURE_2D, 0, dtmp + offset);
  316          s1 += (w * h * 4);
  317          offset += get_mipmapped_size(w, h, 0, 0, 1, DDS_COMPRESS_DXT5);
  318          if(w > 1) w >>= 1;
  319          if(h > 1) h >>= 1;
  320       }
  321 
  322       for(i = j = 0; i < size; i += 16, j += 8)
  323          memcpy(dst + j, dtmp + i, 8);
  324 
  325       g_free(dtmp);
  326       g_free(stmp);
  327    }
  328    else if(format == DDS_COMPRESS_ATI2)
  329    {
  330       size = get_mipmapped_size(width, height, 4, 0, mipmaps, DDS_COMPRESS_NONE);
  331       stmp = g_malloc(size * 2);
  332       memset(stmp, 0, size * 2);
  333 
  334       s1 = stmp;
  335       s2 = stmp + size;
  336 
  337       for(i = j = 0; j < size; i += bpp, j += 4)
  338       {
  339          s1[j + 3] = src[i + 1];
  340          s2[j + 3] = src[i];
  341       }
  342 
  343       size = get_mipmapped_size(width, height, 0, 0, mipmaps, DDS_COMPRESS_DXT5);
  344       dtmp = g_malloc(size * 2);
  345 
  346       d1 = dtmp;
  347       d2 = dtmp + size;
  348 
  349       offset = 0;
  350       w = width;
  351       h = height;
  352 
  353       for(i = 0; i < mipmaps; ++i)
  354       {
  355          glTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT,
  356                       w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, s1);
  357          glGetCompressedTexImageARB(GL_TEXTURE_2D, 0, d1 + offset);
  358          glTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT,
  359                       w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, s2);
  360          glGetCompressedTexImageARB(GL_TEXTURE_2D, 0, d2 + offset);
  361          s1 += (w * h * 4);
  362          s2 += (w * h * 4);
  363          offset += get_mipmapped_size(w, h, 0, 0, 1, DDS_COMPRESS_DXT5);
  364          if(w > 1) w >>= 1;
  365          if(h > 1) h >>= 1;
  366       }
  367 
  368       for(i = 0; i < size; i += 16)
  369       {
  370          memcpy(dst + i + 0, d1 + i, 8);
  371          memcpy(dst + i + 8, d2 + i, 8);
  372       }
  373 
  374       g_free(dtmp);
  375       g_free(stmp);
  376    }
  377 
  378 #endif // #ifdef USE_SOFTWARE_COMPRESSION
  379 }
  380 
  381 int dxt_compress(unsigned char *dst, unsigned char *src, int format,
  382                  unsigned int width, unsigned int height, int bpp,
  383                  int mipmaps)
  384 {
  385    GLenum internal = 0;
  386    GLenum type = 0;
  387    int i, size, w, h;
  388    unsigned int offset;
  389    unsigned char *tmp;
  390 #ifdef USE_SOFTWARE_COMPRESSION
  391    int j;
  392    unsigned char *tmp2, *s, c;
  393 #endif
  394 
  395    if(!(IS_POT(width) && IS_POT(height)))
  396       return(0);
  397 
  398    switch(bpp)
  399    {
  400       case 1: type = GL_LUMINANCE;       break;
  401       case 2: type = GL_LUMINANCE_ALPHA; break;
  402       case 3: type = GL_BGR;             break;
  403       case 4: type = GL_BGRA;            break;
  404    }
  405 
  406    if(format == DDS_COMPRESS_DXT1)
  407    {
  408       internal = (bpp == 4 || bpp == 2) ? GL_COMPRESSED_RGBA_S3TC_DXT1_EXT :
  409                                           GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
  410    }
  411    else if(format == DDS_COMPRESS_DXT3)
  412       internal = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
  413    else if(format == DDS_COMPRESS_DXT5)
  414       internal = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
  415 
  416 #ifdef USE_SOFTWARE_COMPRESSION
  417 
  418    size = get_mipmapped_size(width, height, bpp, 0, mipmaps,
  419                              DDS_COMPRESS_NONE);
  420    tmp = g_malloc(size);
  421    generate_mipmaps_software(tmp, src, width, height, bpp, 0, mipmaps);
  422 
  423    if(bpp == 1)
  424    {
  425       /* grayscale promoted to RGB */
  426 
  427       size = get_mipmapped_size(width, height, 3, 0, mipmaps,
  428                                 DDS_COMPRESS_NONE);
  429       tmp2 = g_malloc(size);
  430 
  431       for(i = j = 0; j < size; ++i, j += 3)
  432       {
  433          tmp2[j + 0] = tmp[i];
  434          tmp2[j + 1] = tmp[i];
  435          tmp2[j + 2] = tmp[i];
  436       }
  437 
  438       g_free(tmp);
  439       tmp = tmp2;
  440       bpp = 3;
  441    }
  442    else if(bpp == 2)
  443    {
  444       /* gray-alpha promoted to RGBA */
  445 
  446       size = get_mipmapped_size(width, height, 4, 0, mipmaps,
  447                                 DDS_COMPRESS_NONE);
  448       tmp2 = g_malloc(size);
  449 
  450       for(i = j = 0; j < size; i += 2, j += 4)
  451       {
  452          tmp2[j + 0] = tmp[i];
  453          tmp2[j + 1] = tmp[i];
  454          tmp2[j + 2] = tmp[i];
  455          tmp2[j + 3] = tmp[i + 1];
  456       }
  457 
  458       g_free(tmp);
  459       tmp = tmp2;
  460       bpp = 4;
  461    }
  462    else /* bpp >= 3 */
  463    {
  464       /* libtxc_dxtn wants BGRA pixels */
  465       for(i = 0; i < size; i += bpp)
  466       {
  467          c = tmp[i];
  468          tmp[i] = tmp[i + 2];
  469          tmp[i + 2] = c;
  470       }
  471    }
  472 
  473    /* add an opaque alpha channel if need be */
  474    if(bpp == 3 && (format == DDS_COMPRESS_DXT3 || format == DDS_COMPRESS_DXT5))
  475    {
  476       size = get_mipmapped_size(width, height, 4, 0, mipmaps,
  477                                 DDS_COMPRESS_NONE);
  478       tmp2 = g_malloc(size);
  479 
  480       for(i = j = 0; j < size; i += bpp, j += 4)
  481       {
  482          tmp2[j + 0] = tmp[i + 0];
  483          tmp2[j + 1] = tmp[i + 1];
  484          tmp2[j + 2] = tmp[i + 2];
  485          tmp2[j + 3] = 255;
  486       }
  487 
  488       g_free(tmp);
  489       tmp = tmp2;
  490       bpp = 4;
  491    }
  492 
  493    offset = 0;
  494    w = width;
  495    h = height;
  496    s = tmp;
  497 
  498    if(format <= DDS_COMPRESS_DXT5)
  499    {
  500       for(i = 0; i < mipmaps; ++i)
  501       {
  502          compress_dxtn(bpp, w, h, s, internal, dst + offset);
  503          s += (w * h * bpp);
  504          offset += get_mipmapped_size(w, h, 0, 0, 1, format);
  505          if(w > 1) w >>= 1;
  506          if(h > 1) h >>= 1;
  507       }
  508    }
  509    else /* 3Dc */
  510       compress_3dc(dst, s, w, h, bpp, mipmaps, format);
  511 
  512    g_free(tmp);
  513 
  514 #else
  515 
  516    if(format >= DDS_COMPRESS_ATI1)
  517    {
  518       size = get_mipmapped_size(width, height, 4, 0, mipmaps, DDS_COMPRESS_NONE);
  519       tmp = g_malloc(size);
  520 
  521       if(GLEW_SGIS_generate_mipmap)
  522       {
  523          glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP_SGIS,
  524                          mipmaps > 1 ? GL_TRUE : GL_FALSE);
  525          glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0,
  526                          type, GL_UNSIGNED_BYTE, src);
  527 
  528          offset = 0;
  529          for(i = 0; i < mipmaps; ++i)
  530          {
  531             glGetTexImage(GL_TEXTURE_2D, i, GL_RGBA, GL_UNSIGNED_BYTE,
  532                           tmp + offset);
  533             offset += get_mipmapped_size(width, height, 4, i, 1,
  534                                          DDS_COMPRESS_NONE);
  535          }
  536       }
  537       else
  538          generate_mipmaps_software(tmp, src, width, height, bpp, 0, mipmaps);
  539 
  540       compress_3dc(dst, tmp, width, height, 4, mipmaps, format);
  541 
  542       g_free(tmp);
  543 
  544       return(1);
  545    }
  546 
  547    if(GLEW_SGIS_generate_mipmap)
  548    {
  549       glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP_SGIS,
  550                       mipmaps > 1 ? GL_TRUE : GL_FALSE);
  551       glTexImage2D(GL_TEXTURE_2D, 0, internal, width, height, 0,
  552                    type, GL_UNSIGNED_BYTE, src);
  553    }
  554    else
  555    {
  556       size = get_mipmapped_size(width, height, bpp, 0, mipmaps,
  557                                 DDS_COMPRESS_NONE);
  558       tmp = g_malloc(size);
  559       generate_mipmaps_software(tmp, src, width, height, bpp, 0, mipmaps);
  560 
  561       offset = 0;
  562       w = width;
  563       h = height;
  564 
  565       for(i = 0; i < mipmaps; ++i)
  566       {
  567          glTexImage2D(GL_TEXTURE_2D, i, internal, w, h, 0, type,
  568                       GL_UNSIGNED_BYTE, tmp + offset);
  569          offset += (w * h * bpp);
  570          if(w > 1) w >>= 1;
  571          if(h > 1) h >>= 1;
  572       }
  573 
  574       g_free(tmp);
  575    }
  576 
  577    glGetCompressedTexImageARB(GL_TEXTURE_2D, 0, dst);
  578 
  579    if(mipmaps > 1)
  580    {
  581       offset = 0;
  582       for(i = 1; i < mipmaps; ++i)
  583       {
  584          glGetTexLevelParameteriv(GL_TEXTURE_2D, i - 1,
  585                                   GL_TEXTURE_COMPRESSED_IMAGE_SIZE_ARB, &size);
  586          offset += size;
  587          glGetCompressedTexImageARB(GL_TEXTURE_2D, i, dst + offset);
  588       }
  589    }
  590 
  591 #endif // #ifdef USE_SOFTWARE_COMPRESSION
  592 
  593    return(1);
  594 }
  595 
  596 #ifdef USE_SOFTWARE_COMPRESSION
  597 
  598 static void decode_color_block(unsigned char *dst, unsigned char *src,
  599                                int w, int h, int rowbytes, int format)
  600 {
  601    int i, x, y;
  602    unsigned int indexes, idx;
  603    unsigned char *d;
  604    unsigned char colors[4][3];
  605    unsigned short c0, c1;
  606 
  607    c0 = GETL16(&src[0]);
  608    c1 = GETL16(&src[2]);
  609 
  610    colors[0][0] = ((c0 >> 11) & 0x1f) << 3;
  611    colors[0][1] = ((c0 >>  5) & 0x3f) << 2;
  612    colors[0][2] = ((c0      ) & 0x1f) << 3;
  613 
  614    colors[1][0] = ((c1 >> 11) & 0x1f) << 3;
  615    colors[1][1] = ((c1 >>  5) & 0x3f) << 2;
  616    colors[1][2] = ((c1      ) & 0x1f) << 3;
  617 
  618    if((c0 > c1) || (format == DDS_COMPRESS_DXT5))
  619    {
  620       for(i = 0; i < 3; ++i)
  621       {
  622          colors[2][i] = (2 * colors[0][i] + colors[1][i] + 1) / 3;
  623          colors[3][i] = (2 * colors[1][i] + colors[0][i] + 1) / 3;
  624       }
  625    }
  626    else
  627    {
  628       for(i = 0; i < 3; ++i)
  629       {
  630          colors[2][i] = (colors[0][i] + colors[1][i] + 1) >> 1;
  631          colors[3][i] = 255;
  632       }
  633    }
  634 
  635    src += 4;
  636    for(y = 0; y < h; ++y)
  637    {
  638       d = dst + (y * rowbytes);
  639       indexes = src[y];
  640       for(x = 0; x < w; ++x)
  641       {
  642          idx = indexes & 0x03;
  643          d[0] = colors[idx][0];
  644          d[1] = colors[idx][1];
  645          d[2] = colors[idx][2];
  646          if(format == DDS_COMPRESS_DXT1)
  647             d[3] = ((c0 <= c1) && idx == 3) ? 0 : 255;
  648          indexes >>= 2;
  649          d += 4;
  650       }
  651    }
  652 }
  653 
  654 static void decode_dxt3_alpha(unsigned char *dst, unsigned char *src,
  655                               int w, int h, int rowbytes)
  656 {
  657    int x, y;
  658    unsigned char *d;
  659    unsigned int bits;
  660 
  661    for(y = 0; y < h; ++y)
  662    {
  663       d = dst + (y * rowbytes);
  664       bits = GETL16(&src[2 * y]);
  665       bits = GETL16(&src[2 * y]);
  666       for(x = 0; x < w; ++x)
  667       {
  668          d[0] = (bits & 0x0f) * 17;
  669          bits >>= 4;
  670          d += 4;
  671       }
  672    }
  673 }
  674 
  675 #endif // #ifdef USE_SOFTWARE_COMPRESSION
  676 
  677 static void decode_dxt5_alpha(unsigned char *dst, unsigned char *src,
  678                               int w, int h, int bpp, int rowbytes)
  679 {
  680    int x, y, code;
  681    unsigned char *d;
  682    unsigned char a0 = src[0];
  683    unsigned char a1 = src[1];
  684    unsigned long long bits = GETL64(src) >> 16;
  685 
  686    for(y = 0; y < h; ++y)
  687    {
  688       d = dst + (y * rowbytes);
  689       for(x = 0; x < w; ++x)
  690       {
  691          code = ((unsigned int)bits) & 0x07;
  692          if(code == 0)
  693             d[0] = a0;
  694          else if(code == 1)
  695             d[0] = a1;
  696          else if(a0 > a1)
  697             d[0] = ((8 - code) * a0 + (code - 1) * a1) / 7;
  698          else if(code >= 6)
  699             d[0] = (code == 6) ? 0 : 255;
  700          else
  701             d[0] = ((6 - code) * a0 + (code - 1) * a1) / 5;
  702          bits >>= 3;
  703          d += bpp;
  704       }
  705       if(w < 4) bits >>= (3 * (4 - w));
  706    }
  707 }
  708 
  709 int dxt_decompress(unsigned char *dst, unsigned char *src, int format,
  710                    unsigned int size, unsigned int width, unsigned int height,
  711                    int bpp)
  712 {
  713 #ifdef USE_SOFTWARE_COMPRESSION
  714 
  715    unsigned char *d, *s;
  716    unsigned int x, y, sx, sy;
  717 
  718    if(!(IS_POT(width) && IS_POT(height)))
  719       return(0);
  720 
  721    sx = (width  < 4) ? width  : 4;
  722    sy = (height < 4) ? height : 4;
  723 
  724    s = src;
  725 
  726    for(y = 0; y < height; y += 4)
  727    {
  728       for(x = 0; x < width; x += 4)
  729       {
  730          d = dst + (y * width + x) * bpp;
  731          if(format == DDS_COMPRESS_DXT3)
  732          {
  733             decode_dxt3_alpha(d + 3, s, sx, sy, width * bpp);
  734             s += 8;
  735          }
  736          else if(format == DDS_COMPRESS_DXT5)
  737          {
  738             decode_dxt5_alpha(d + 3, s, sx, sy, bpp, width * bpp);
  739             s += 8;
  740          }
  741          else if(format == DDS_COMPRESS_ATI1)
  742          {
  743             decode_dxt5_alpha(d, s, sx, sy, bpp, width * bpp);
  744             s += 8;
  745          }
  746          else if(format == DDS_COMPRESS_ATI2)
  747          {
  748             decode_dxt5_alpha(d, s + 8, sx, sy, bpp, width * bpp);
  749             decode_dxt5_alpha(d + 1, s, sx, sy, bpp, width * bpp);
  750             s += 16;
  751          }
  752 
  753          if(format <= DDS_COMPRESS_DXT5)
  754          {
  755             decode_color_block(d, s, sx, sy, width * bpp, format);
  756             s += 8;
  757          }
  758       }
  759    }
  760 
  761 #else // #ifdef USE_SOFTWARE_COMPRESSION
  762 
  763    GLenum internal = GL_NONE, type = GL_RGB;
  764    unsigned char *d, *s;
  765    unsigned int x, y, sx, sy;
  766 
  767    if(!(IS_POT(width) && IS_POT(height)))
  768       return(0);
  769 
  770    if(format >= DDS_COMPRESS_ATI1) /* 3Dc */
  771    {
  772       sx = (width  < 4) ? width  : 4;
  773       sy = (height < 4) ? height : 4;
  774 
  775       s = src;
  776 
  777       for(y = 0; y < height; y += 4)
  778       {
  779          for(x = 0; x < width; x += 4)
  780          {
  781             d = dst + (y * width + x) * bpp;
  782             if(format == DDS_COMPRESS_ATI1)
  783             {
  784                decode_dxt5_alpha(d, s, sx, sy, bpp, width * bpp);
  785                s += 8;
  786             }
  787             else if(format == DDS_COMPRESS_ATI2)
  788             {
  789                decode_dxt5_alpha(d, s + 8, sx, sy, bpp, width * bpp);
  790                decode_dxt5_alpha(d + 1, s, sx, sy, bpp, width * bpp);
  791                s += 16;
  792             }
  793          }
  794       }
  795       return(1);
  796    }
  797 
  798    switch(bpp)
  799    {
  800       case 1: type = GL_LUMINANCE;       break;
  801       case 2: type = GL_LUMINANCE_ALPHA; break;
  802       case 3: type = GL_RGB;             break;
  803       case 4: type = GL_RGBA;            break;
  804    }
  805 
  806    switch(format)
  807    {
  808       case DDS_COMPRESS_DXT1:
  809          internal = (bpp == 4) ? GL_COMPRESSED_RGBA_S3TC_DXT1_EXT :
  810                                  GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
  811          break;
  812       case DDS_COMPRESS_DXT3:
  813          internal = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
  814          break;
  815       case DDS_COMPRESS_DXT5:
  816          internal = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
  817          break;
  818    }
  819 
  820    glCompressedTexImage2DARB(GL_TEXTURE_2D, 0, internal, width, height, 0, size, src);
  821    glGetTexImage(GL_TEXTURE_2D, 0, type, GL_UNSIGNED_BYTE, dst);
  822 
  823 #endif // #ifdef USE_SOFTWARE_COMPRESSION
  824 
  825    return(1);
  826 }
  827 
  828 float cubic_interpolate(float a, float b, float c, float d, float x)
  829 {
  830    float v0, v1, v2, v3, x2;
  831 
  832    x2 = x * x;
  833    v0 = d - c - a + b;
  834    v1 = a - b - v0;
  835    v2 = c - a;
  836    v3 = b;
  837 
  838    return(v0 * x * x2 + v1 * x2 + v2 * x + v3);
  839 }
  840 
  841 static void scale_image_cubic(unsigned char *dst, int dw, int dh,
  842                               unsigned char *src, int sw, int sh,
  843                               int bpp)
  844 {
  845    int n, x, y;
  846    int ix, iy;
  847    float fx, fy;
  848    float dx, dy, val;
  849    float r0, r1, r2, r3;
  850    int srowbytes = sw * bpp;
  851    int drowbytes = dw * bpp;
  852 
  853 #define VAL(x, y, c) \
  854    (float)src[((y) < 0 ? 0 : (y) >= sh ? sh - 1 : (y)) * srowbytes + \
  855               (((x) < 0 ? 0 : (x) >= sw ? sw - 1 : (x)) * bpp) + c]
  856 
  857    for(y = 0; y < dh; ++y)
  858    {
  859       fy = ((float)y / (float)dh) * (float)sh;
  860       iy = (int)fy;
  861       dy = fy - (float)iy;
  862       for(x = 0; x < dw; ++x)
  863       {
  864          fx = ((float)x / (float)dw) * (float)sw;
  865          ix = (int)fx;
  866          dx = fx - (float)ix;
  867 
  868          for(n = 0; n < bpp; ++n)
  869          {
  870             r0 = cubic_interpolate(VAL(ix - 1, iy - 1, n),
  871                                    VAL(ix,     iy - 1, n),
  872                                    VAL(ix + 1, iy - 1, n),
  873                                    VAL(ix + 2, iy - 1, n), dx);
  874             r1 = cubic_interpolate(VAL(ix - 1, iy,     n),
  875                                    VAL(ix,     iy,     n),
  876                                    VAL(ix + 1, iy,     n),
  877                                    VAL(ix + 2, iy,     n), dx);
  878             r2 = cubic_interpolate(VAL(ix - 1, iy + 1, n),
  879                                    VAL(ix,     iy + 1, n),
  880                                    VAL(ix + 1, iy + 1, n),
  881                                    VAL(ix + 2, iy + 1, n), dx);
  882             r3 = cubic_interpolate(VAL(ix - 1, iy + 2, n),
  883                                    VAL(ix,     iy + 2, n),
  884                                    VAL(ix + 1, iy + 2, n),
  885                                    VAL(ix + 2, iy + 2, n), dx);
  886             val = cubic_interpolate(r0, r1, r2, r3, dy);
  887             if(val <   0) val = 0;
  888             if(val > 255) val = 255;
  889             dst[y * drowbytes + (x * bpp) + n] = (unsigned char)val;
  890          }
  891       }
  892    }
  893 #undef VAL
  894 }
  895 
  896 static void scale_image_nearest(unsigned char *dst, int dw, int dh,
  897                                 unsigned char *src, int sw, int sh,
  898                                 int bpp)
  899 {
  900    int n, x, y;
  901    int ix, iy;
  902    int srowbytes = sw * bpp;
  903    int drowbytes = dw * bpp;
  904 
  905    for(y = 0; y < dh; ++y)
  906    {
  907       iy = (y * sh + sh / 2) / dh;
  908       for(x = 0; x < dw; ++x)
  909       {
  910          ix = (x * sw + sw / 2) / dw;
  911          for(n = 0; n < bpp; ++n)
  912          {
  913             dst[y * drowbytes + (x * bpp) + n] =
  914                src[iy * srowbytes + (ix * bpp) + n];
  915          }
  916       }
  917    }
  918 }
  919 
  920 static int generate_mipmaps_software(unsigned char *dst, unsigned char *src,
  921                                      unsigned int width, unsigned int height,
  922                                      int bpp, int indexed, int mipmaps)
  923 {
  924    int i;
  925    unsigned int w, h;
  926    unsigned int offset;
  927 
  928    memcpy(dst, src, width * height * bpp);
  929    offset = width * height * bpp;
  930 
  931    for(i = 1; i < mipmaps; ++i)
  932    {
  933       w = width  >> i;
  934       h = height >> i;
  935       if(w < 1) w = 1;
  936       if(h < 1) h = 1;
  937 
  938       if(indexed)
  939          scale_image_nearest(dst + offset, w, h, src, width, height, bpp);
  940       else
  941          scale_image_cubic(dst + offset, w, h, src, width, height, bpp);
  942 
  943       offset += (w * h * bpp);
  944    }
  945 
  946    return(1);
  947 }
  948 
  949 int generate_mipmaps(unsigned char *dst, unsigned char *src,
  950                      unsigned int width, unsigned int height, int bpp,
  951                      int indexed, int mipmaps)
  952 {
  953    int i;
  954    unsigned int w, h;
  955    GLenum internal = 0;
  956    GLenum format = 0;
  957    unsigned int offset;
  958 
  959    if(!GLEW_SGIS_generate_mipmap || indexed ||
  960       (!(IS_POT(width) && IS_POT(height)) &&
  961        !GLEW_ARB_texture_non_power_of_two))
  962    {
  963       return(generate_mipmaps_software(dst, src, width, height, bpp, indexed,
  964                                        mipmaps));
  965    }
  966 
  967    switch(bpp)
  968    {
  969       case 1: internal = format = GL_LUMINANCE;       break;
  970       case 2: internal = format = GL_LUMINANCE_ALPHA; break;
  971       case 3: internal = GL_RGB; format = GL_BGR;     break;
  972       case 4: internal = GL_RGBA; format = GL_BGRA;   break;
  973    }
  974 
  975    glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP_SGIS, GL_TRUE);
  976    glTexImage2D(GL_TEXTURE_2D, 0, internal, width, height, 0,
  977                 format, GL_UNSIGNED_BYTE, src);
  978 
  979    memcpy(dst, src, width * height * bpp);
  980 
  981    offset = width * height * bpp;
  982 
  983    for(i = 1; i < mipmaps; ++i)
  984    {
  985       w = width  >> i;
  986       h = height >> i;
  987       if(w < 1) w = 1;
  988       if(h < 1) h = 1;
  989 
  990       glGetTexImage(GL_TEXTURE_2D, i, format, GL_UNSIGNED_BYTE, dst + offset);
  991 
  992       offset += (w * h * bpp);
  993    }
  994 
  995    return(1);
  996 }
  997 
  998 static void scale_volume_image_cubic(unsigned char *dst, int dw, int dh, int dd,
  999                                      unsigned char *src, int sw, int sh, int sd,
 1000                                      int bpp)
 1001 {
 1002    int n, x, y, z;
 1003    int ix, iy, iz;
 1004    float fx, fy, fz;
 1005    float dx, dy, dz, val;
 1006    float r0, r1, r2, r3;
 1007    float v0, v1, v2, v3;
 1008    int srowbytes = sw * bpp;
 1009    int drowbytes = dw * bpp;
 1010    int sslicebytes = sw * sh * bpp;
 1011    int dslicebytes = dw * dh * bpp;
 1012 
 1013 #define VAL(x, y, z, c) \
 1014    (float)src[(((z) < 0 ? 0 : (z) >= sd ? sd - 1 : (z)) * sslicebytes) + \
 1015               (((y) < 0 ? 0 : (y) >= sh ? sh - 1 : (y)) * srowbytes) + \
 1016               (((x) < 0 ? 0 : (x) >= sw ? sw - 1 : (x)) * bpp) + c]
 1017 
 1018    for(z = 0; z < dd; ++z)
 1019    {
 1020       fz = ((float)z / (float)dd) * (float)sd;
 1021       iz = (int)fz;
 1022       dz = fz - (float)iz;
 1023       for(y = 0; y < dh; ++y)
 1024       {
 1025          fy = ((float)y / (float)dh) * (float)sh;
 1026          iy = (int)fy;
 1027          dy = fy - (float)iy;
 1028          for(x = 0; x < dw; ++x)
 1029          {
 1030             fx = ((float)x / (float)dw) * (float)sw;
 1031             ix = (int)fx;
 1032             dx = fx - (float)ix;
 1033             for(n = 0; n < bpp; ++n)
 1034             {
 1035                r0 = cubic_interpolate(VAL(ix - 1, iy - 1, z - 1, n),
 1036                                       VAL(ix,     iy - 1, z - 1, n),
 1037                                       VAL(ix + 1, iy - 1, z - 1, n),
 1038                                       VAL(ix + 2, iy - 1, z - 1, n), dx);
 1039                r1 = cubic_interpolate(VAL(ix - 1, iy,     z - 1, n),
 1040                                       VAL(ix,     iy,     z - 1, n),
 1041                                       VAL(ix + 1, iy,     z - 1, n),
 1042                                       VAL(ix + 2, iy,     z - 1, n), dx);
 1043                r2 = cubic_interpolate(VAL(ix - 1, iy + 1, z - 1, n),
 1044                                       VAL(ix,     iy + 1, z - 1, n),
 1045                                       VAL(ix + 1, iy + 1, z - 1, n),
 1046                                       VAL(ix + 2, iy + 1, z - 1, n), dx);
 1047                r3 = cubic_interpolate(VAL(ix - 1, iy + 2, z - 1, n),
 1048                                       VAL(ix,     iy + 2, z - 1, n),
 1049                                       VAL(ix + 1, iy + 2, z - 1, n),
 1050                                       VAL(ix + 2, iy + 2, z - 1, n), dx);
 1051                v0 = cubic_interpolate(r0, r1, r2, r3, dy);
 1052 
 1053                r0 = cubic_interpolate(VAL(ix - 1, iy - 1, z, n),
 1054                                       VAL(ix,     iy - 1, z, n),
 1055                                       VAL(ix + 1, iy - 1, z, n),
 1056                                       VAL(ix + 2, iy - 1, z, n), dx);
 1057                r1 = cubic_interpolate(VAL(ix - 1, iy,     z, n),
 1058                                       VAL(ix,     iy,     z, n),
 1059                                       VAL(ix + 1, iy,     z, n),
 1060                                       VAL(ix + 2, iy,     z, n), dx);
 1061                r2 = cubic_interpolate(VAL(ix - 1, iy + 1, z, n),
 1062                                       VAL(ix,     iy + 1, z, n),
 1063                                       VAL(ix + 1, iy + 1, z, n),
 1064                                       VAL(ix + 2, iy + 1, z, n), dx);
 1065                r3 = cubic_interpolate(VAL(ix - 1, iy + 2, z, n),
 1066                                       VAL(ix,     iy + 2, z, n),
 1067                                       VAL(ix + 1, iy + 2, z, n),
 1068                                       VAL(ix + 2, iy + 2, z, n), dx);
 1069                v1 = cubic_interpolate(r0, r1, r2, r3, dy);
 1070 
 1071                r0 = cubic_interpolate(VAL(ix - 1, iy - 1, z + 1, n),
 1072                                       VAL(ix,     iy - 1, z + 1, n),
 1073                                       VAL(ix + 1, iy - 1, z + 1, n),
 1074                                       VAL(ix + 2, iy - 1, z + 1, n), dx);
 1075                r1 = cubic_interpolate(VAL(ix - 1, iy,     z + 1, n),
 1076                                       VAL(ix,     iy,     z + 1, n),
 1077                                       VAL(ix + 1, iy,     z + 1, n),
 1078                                       VAL(ix + 2, iy,     z + 1, n), dx);
 1079                r2 = cubic_interpolate(VAL(ix - 1, iy + 1, z + 1, n),
 1080                                       VAL(ix,     iy + 1, z + 1, n),
 1081                                       VAL(ix + 1, iy + 1, z + 1, n),
 1082                                       VAL(ix + 2, iy + 1, z + 1, n), dx);
 1083                r3 = cubic_interpolate(VAL(ix - 1, iy + 2, z + 1, n),
 1084                                       VAL(ix,     iy + 2, z + 1, n),
 1085                                       VAL(ix + 1, iy + 2, z + 1, n),
 1086                                       VAL(ix + 2, iy + 2, z + 1, n), dx);
 1087                v2 = cubic_interpolate(r0, r1, r2, r3, dy);
 1088 
 1089                r0 = cubic_interpolate(VAL(ix - 1, iy - 1, z + 2, n),
 1090                                       VAL(ix,     iy - 1, z + 2, n),
 1091                                       VAL(ix + 1, iy - 1, z + 2, n),
 1092                                       VAL(ix + 2, iy - 1, z + 2, n), dx);
 1093                r1 = cubic_interpolate(VAL(ix - 1, iy,     z + 2, n),
 1094                                       VAL(ix,     iy,     z + 2, n),
 1095                                       VAL(ix + 1, iy,     z + 2, n),
 1096                                       VAL(ix + 2, iy,     z + 2, n), dx);
 1097                r2 = cubic_interpolate(VAL(ix - 1, iy + 1, z + 2, n),
 1098                                       VAL(ix,     iy + 1, z + 2, n),
 1099                                       VAL(ix + 1, iy + 1, z + 2, n),
 1100                                       VAL(ix + 2, iy + 1, z + 2, n), dx);
 1101                r3 = cubic_interpolate(VAL(ix - 1, iy + 2, z + 2, n),
 1102                                       VAL(ix,     iy + 2, z + 2, n),
 1103                                       VAL(ix + 1, iy + 2, z + 2, n),
 1104                                       VAL(ix + 2, iy + 2, z + 2, n), dx);
 1105                v3 = cubic_interpolate(r0, r1, r2, r3, dy);
 1106 
 1107                val = cubic_interpolate(v0, v1, v2, v3, dz);
 1108 
 1109                if(val <   0) val = 0;
 1110                if(val > 255) val = 255;
 1111 
 1112                dst[(z * dslicebytes) + (y * drowbytes) + (x * bpp) + n] =
 1113                   (unsigned char)val;
 1114             }
 1115          }
 1116       }
 1117    }
 1118 #undef VAL
 1119 }
 1120 
 1121 static void scale_volume_image_nearest(unsigned char *dst, int dw, int dh, int dd,
 1122                                        unsigned char *src, int sw, int sh, int sd,
 1123                                        int bpp)
 1124 {
 1125    int n, x, y, z;
 1126    int ix, iy, iz;
 1127 
 1128    for(z = 0; z < dd; ++z)
 1129    {
 1130       iz = (z * sd + sd / 2) / dd;
 1131       for(y = 0; y < dh; ++y)
 1132       {
 1133          iy = (y * sh + sh / 2) / dh;
 1134          for(x = 0; x < dw; ++x)
 1135          {
 1136             ix = (x * sw + sw / 2) / dw;
 1137             for(n = 0; n < bpp; ++n)
 1138             {
 1139                dst[(z * (dw * dh)) + (y * dw) + (x * bpp) + n] =
 1140                   src[(iz * (sw * sh)) + (iy * sw) + (ix * bpp) + n];
 1141             }
 1142          }
 1143       }
 1144    }
 1145 }
 1146 
 1147 static int generate_volume_mipmaps_software(unsigned char *dst, unsigned char *src,
 1148                                             unsigned int width, unsigned int height,
 1149                                             unsigned int depth, int bpp, int indexed,
 1150                                             int mipmaps)
 1151 {
 1152    int i;
 1153    unsigned int w, h, d;
 1154    unsigned int offset;
 1155 
 1156    memcpy(dst, src, width * height * depth * bpp);
 1157    offset = width * height * depth * bpp;
 1158 
 1159    for(i = 1; i < mipmaps; ++i)
 1160    {
 1161       w = width  >> i;
 1162       h = height >> i;
 1163       d = depth  >> i;
 1164       if(w < 1) w = 1;
 1165       if(h < 1) h = 1;
 1166       if(d < 1) d = 1;
 1167 
 1168       if(indexed)
 1169       {
 1170          scale_volume_image_nearest(dst + offset, w, h, d, src, width, height,
 1171                                     depth, bpp);
 1172       }
 1173       else
 1174       {
 1175          scale_volume_image_cubic(dst + offset, w, h, d, src, width, height,
 1176                                   depth, bpp);
 1177       }
 1178 
 1179       offset += (w * h * d * bpp);
 1180    }
 1181 
 1182    return(1);
 1183 }
 1184 
 1185 int generate_volume_mipmaps(unsigned char *dst, unsigned char *src,
 1186                             unsigned int width, unsigned int height,
 1187                             unsigned int depth, int bpp, int indexed,
 1188                             int mipmaps)
 1189 {
 1190    int i;
 1191    unsigned int w, h, d;
 1192    GLenum internal = 0;
 1193    GLenum format = 0;
 1194    unsigned int offset;
 1195 
 1196    if(!GLEW_SGIS_generate_mipmap || indexed ||
 1197       (!(IS_POT(width) && IS_POT(height) && IS_POT(depth)) &&
 1198        !GLEW_ARB_texture_non_power_of_two))
 1199    {
 1200       return(generate_volume_mipmaps_software(dst, src, width, height, depth, bpp,
 1201                                               indexed, mipmaps));
 1202    }
 1203 
 1204    switch(bpp)
 1205    {
 1206       case 1: internal = format = GL_LUMINANCE;       break;
 1207       case 2: internal = format = GL_LUMINANCE_ALPHA; break;
 1208       case 3: internal = GL_RGB; format = GL_BGR;     break;
 1209       case 4: internal = GL_RGBA; format = GL_BGRA;   break;
 1210    }
 1211 
 1212    glTexParameteri(GL_TEXTURE_3D, GL_GENERATE_MIPMAP_SGIS, GL_TRUE);
 1213    glTexImage3D(GL_TEXTURE_3D, 0, internal, width, height, depth, 0,
 1214                 format, GL_UNSIGNED_BYTE, src);
 1215 
 1216    memcpy(dst, src, width * height * bpp * depth);
 1217 
 1218    offset = width * height * bpp * depth;
 1219 
 1220    for(i = 1; i < mipmaps; ++i)
 1221    {
 1222       w = width >> i;
 1223       h = height >> i;
 1224       d = depth >> i;
 1225       if(w < 1) w = 1;
 1226       if(h < 1) h = 1;
 1227       if(d < 1) d = 1;
 1228 
 1229       glGetTexImage(GL_TEXTURE_3D, i, format, GL_UNSIGNED_BYTE, dst + offset);
 1230 
 1231       offset += (w * h * bpp * d);
 1232    }
 1233 
 1234    return(1);
 1235 }

ViewVC Help
Powered by ViewVC 1.0.4