Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * Mesa 3-D graphics library
  3.  *
  4.  * Copyright (C) 1999-2007  Brian Paul   All Rights Reserved.
  5.  * Copyright (c) 2008 VMware, Inc.
  6.  *
  7.  * Permission is hereby granted, free of charge, to any person obtaining a
  8.  * copy of this software and associated documentation files (the "Software"),
  9.  * to deal in the Software without restriction, including without limitation
  10.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  11.  * and/or sell copies of the Software, and to permit persons to whom the
  12.  * Software is furnished to do so, subject to the following conditions:
  13.  *
  14.  * The above copyright notice and this permission notice shall be included
  15.  * in all copies or substantial portions of the Software.
  16.  *
  17.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  18.  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  19.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  20.  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
  21.  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  22.  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  23.  * OTHER DEALINGS IN THE SOFTWARE.
  24.  */
  25.  
  26.  
  27. /**
  28.  * \file texcompress_s3tc.c
  29.  * GL_EXT_texture_compression_s3tc support.
  30.  */
  31.  
  32. #ifndef USE_EXTERNAL_DXTN_LIB
  33. #define USE_EXTERNAL_DXTN_LIB 1
  34. #endif
  35.  
  36. #include "glheader.h"
  37. #include "imports.h"
  38. #include "colormac.h"
  39. #include "dlopen.h"
  40. #include "image.h"
  41. #include "macros.h"
  42. #include "mtypes.h"
  43. #include "texcompress.h"
  44. #include "texcompress_s3tc.h"
  45. #include "texstore.h"
  46. #include "format_unpack.h"
  47.  
  48.  
  49. #if defined(_WIN32) || defined(WIN32)
  50. #define DXTN_LIBNAME "dxtn.dll"
  51. #define RTLD_LAZY 0
  52. #define RTLD_GLOBAL 0
  53. #elif defined(__DJGPP__)
  54. #define DXTN_LIBNAME "dxtn.dxe"
  55. #else
  56. #define DXTN_LIBNAME "libtxc_dxtn.so"
  57. #endif
  58.  
  59. typedef void (*dxtFetchTexelFuncExt)( GLint srcRowstride, const GLubyte *pixdata, GLint col, GLint row, GLvoid *texelOut );
  60.  
  61. static dxtFetchTexelFuncExt fetch_ext_rgb_dxt1 = NULL;
  62. static dxtFetchTexelFuncExt fetch_ext_rgba_dxt1 = NULL;
  63. static dxtFetchTexelFuncExt fetch_ext_rgba_dxt3 = NULL;
  64. static dxtFetchTexelFuncExt fetch_ext_rgba_dxt5 = NULL;
  65.  
  66. typedef void (*dxtCompressTexFuncExt)(GLint srccomps, GLint width,
  67.                                       GLint height, const GLubyte *srcPixData,
  68.                                       GLenum destformat, GLubyte *dest,
  69.                                       GLint dstRowStride);
  70.  
  71. static dxtCompressTexFuncExt ext_tx_compress_dxtn = NULL;
  72.  
  73. static void *dxtlibhandle = NULL;
  74.  
  75.  
  76. void
  77. _mesa_init_texture_s3tc( struct gl_context *ctx )
  78. {
  79.    /* called during context initialization */
  80.    ctx->Mesa_DXTn = GL_FALSE;
  81. #if USE_EXTERNAL_DXTN_LIB
  82.    if (!dxtlibhandle) {
  83.       dxtlibhandle = _mesa_dlopen(DXTN_LIBNAME, 0);
  84.       if (!dxtlibhandle) {
  85.          _mesa_warning(ctx, "couldn't open " DXTN_LIBNAME ", software DXTn "
  86.             "compression/decompression unavailable");
  87.       }
  88.       else {
  89.          /* the fetch functions are not per context! Might be problematic... */
  90.          fetch_ext_rgb_dxt1 = (dxtFetchTexelFuncExt)
  91.             _mesa_dlsym(dxtlibhandle, "fetch_2d_texel_rgb_dxt1");
  92.          fetch_ext_rgba_dxt1 = (dxtFetchTexelFuncExt)
  93.             _mesa_dlsym(dxtlibhandle, "fetch_2d_texel_rgba_dxt1");
  94.          fetch_ext_rgba_dxt3 = (dxtFetchTexelFuncExt)
  95.             _mesa_dlsym(dxtlibhandle, "fetch_2d_texel_rgba_dxt3");
  96.          fetch_ext_rgba_dxt5 = (dxtFetchTexelFuncExt)
  97.             _mesa_dlsym(dxtlibhandle, "fetch_2d_texel_rgba_dxt5");
  98.          ext_tx_compress_dxtn = (dxtCompressTexFuncExt)
  99.             _mesa_dlsym(dxtlibhandle, "tx_compress_dxtn");
  100.  
  101.          if (!fetch_ext_rgb_dxt1 ||
  102.              !fetch_ext_rgba_dxt1 ||
  103.              !fetch_ext_rgba_dxt3 ||
  104.              !fetch_ext_rgba_dxt5 ||
  105.              !ext_tx_compress_dxtn) {
  106.             _mesa_warning(ctx, "couldn't reference all symbols in "
  107.                DXTN_LIBNAME ", software DXTn compression/decompression "
  108.                "unavailable");
  109.             fetch_ext_rgb_dxt1 = NULL;
  110.             fetch_ext_rgba_dxt1 = NULL;
  111.             fetch_ext_rgba_dxt3 = NULL;
  112.             fetch_ext_rgba_dxt5 = NULL;
  113.             ext_tx_compress_dxtn = NULL;
  114.             _mesa_dlclose(dxtlibhandle);
  115.             dxtlibhandle = NULL;
  116.          }
  117.       }
  118.    }
  119.    if (dxtlibhandle) {
  120.       ctx->Mesa_DXTn = GL_TRUE;
  121.    }
  122. #else
  123.    (void) ctx;
  124. #endif
  125. }
  126.  
  127. /**
  128.  * Store user's image in rgb_dxt1 format.
  129.  */
  130. GLboolean
  131. _mesa_texstore_rgb_dxt1(TEXSTORE_PARAMS)
  132. {
  133.    const GLubyte *pixels;
  134.    GLubyte *dst;
  135.    const GLubyte *tempImage = NULL;
  136.  
  137.    ASSERT(dstFormat == MESA_FORMAT_RGB_DXT1 ||
  138.           dstFormat == MESA_FORMAT_SRGB_DXT1);
  139.  
  140.    if (srcFormat != GL_RGB ||
  141.        srcType != GL_UNSIGNED_BYTE ||
  142.        ctx->_ImageTransferState ||
  143.        srcPacking->RowLength != srcWidth ||
  144.        srcPacking->SwapBytes) {
  145.       /* convert image to RGB/GLubyte */
  146.       tempImage = _mesa_make_temp_ubyte_image(ctx, dims,
  147.                                              baseInternalFormat,
  148.                                              _mesa_get_format_base_format(dstFormat),
  149.                                              srcWidth, srcHeight, srcDepth,
  150.                                              srcFormat, srcType, srcAddr,
  151.                                              srcPacking);
  152.       if (!tempImage)
  153.          return GL_FALSE; /* out of memory */
  154.       pixels = tempImage;
  155.       srcFormat = GL_RGB;
  156.    }
  157.    else {
  158.       pixels = _mesa_image_address2d(srcPacking, srcAddr, srcWidth, srcHeight,
  159.                                      srcFormat, srcType, 0, 0);
  160.    }
  161.  
  162.    dst = dstSlices[0];
  163.  
  164.    if (ext_tx_compress_dxtn) {
  165.       (*ext_tx_compress_dxtn)(3, srcWidth, srcHeight, pixels,
  166.                               GL_COMPRESSED_RGB_S3TC_DXT1_EXT,
  167.                               dst, dstRowStride);
  168.    }
  169.    else {
  170.       _mesa_warning(ctx, "external dxt library not available: texstore_rgb_dxt1");
  171.    }
  172.  
  173.    free((void *) tempImage);
  174.  
  175.    return GL_TRUE;
  176. }
  177.  
  178.  
  179. /**
  180.  * Store user's image in rgba_dxt1 format.
  181.  */
  182. GLboolean
  183. _mesa_texstore_rgba_dxt1(TEXSTORE_PARAMS)
  184. {
  185.    const GLubyte *pixels;
  186.    GLubyte *dst;
  187.    const GLubyte *tempImage = NULL;
  188.  
  189.    ASSERT(dstFormat == MESA_FORMAT_RGBA_DXT1 ||
  190.           dstFormat == MESA_FORMAT_SRGBA_DXT1);
  191.  
  192.    if (srcFormat != GL_RGBA ||
  193.        srcType != GL_UNSIGNED_BYTE ||
  194.        ctx->_ImageTransferState ||
  195.        srcPacking->RowLength != srcWidth ||
  196.        srcPacking->SwapBytes) {
  197.       /* convert image to RGBA/GLubyte */
  198.       tempImage = _mesa_make_temp_ubyte_image(ctx, dims,
  199.                                              baseInternalFormat,
  200.                                              _mesa_get_format_base_format(dstFormat),
  201.                                              srcWidth, srcHeight, srcDepth,
  202.                                              srcFormat, srcType, srcAddr,
  203.                                              srcPacking);
  204.       if (!tempImage)
  205.          return GL_FALSE; /* out of memory */
  206.       pixels = tempImage;
  207.       srcFormat = GL_RGBA;
  208.    }
  209.    else {
  210.       pixels = _mesa_image_address2d(srcPacking, srcAddr, srcWidth, srcHeight,
  211.                                      srcFormat, srcType, 0, 0);
  212.    }
  213.  
  214.    dst = dstSlices[0];
  215.  
  216.    if (ext_tx_compress_dxtn) {
  217.       (*ext_tx_compress_dxtn)(4, srcWidth, srcHeight, pixels,
  218.                               GL_COMPRESSED_RGBA_S3TC_DXT1_EXT,
  219.                               dst, dstRowStride);
  220.    }
  221.    else {
  222.       _mesa_warning(ctx, "external dxt library not available: texstore_rgba_dxt1");
  223.    }
  224.  
  225.    free((void*) tempImage);
  226.  
  227.    return GL_TRUE;
  228. }
  229.  
  230.  
  231. /**
  232.  * Store user's image in rgba_dxt3 format.
  233.  */
  234. GLboolean
  235. _mesa_texstore_rgba_dxt3(TEXSTORE_PARAMS)
  236. {
  237.    const GLubyte *pixels;
  238.    GLubyte *dst;
  239.    const GLubyte *tempImage = NULL;
  240.  
  241.    ASSERT(dstFormat == MESA_FORMAT_RGBA_DXT3 ||
  242.           dstFormat == MESA_FORMAT_SRGBA_DXT3);
  243.  
  244.    if (srcFormat != GL_RGBA ||
  245.        srcType != GL_UNSIGNED_BYTE ||
  246.        ctx->_ImageTransferState ||
  247.        srcPacking->RowLength != srcWidth ||
  248.        srcPacking->SwapBytes) {
  249.       /* convert image to RGBA/GLubyte */
  250.       tempImage = _mesa_make_temp_ubyte_image(ctx, dims,
  251.                                              baseInternalFormat,
  252.                                              _mesa_get_format_base_format(dstFormat),
  253.                                              srcWidth, srcHeight, srcDepth,
  254.                                              srcFormat, srcType, srcAddr,
  255.                                              srcPacking);
  256.       if (!tempImage)
  257.          return GL_FALSE; /* out of memory */
  258.       pixels = tempImage;
  259.    }
  260.    else {
  261.       pixels = _mesa_image_address2d(srcPacking, srcAddr, srcWidth, srcHeight,
  262.                                      srcFormat, srcType, 0, 0);
  263.    }
  264.  
  265.    dst = dstSlices[0];
  266.  
  267.    if (ext_tx_compress_dxtn) {
  268.       (*ext_tx_compress_dxtn)(4, srcWidth, srcHeight, pixels,
  269.                               GL_COMPRESSED_RGBA_S3TC_DXT3_EXT,
  270.                               dst, dstRowStride);
  271.    }
  272.    else {
  273.       _mesa_warning(ctx, "external dxt library not available: texstore_rgba_dxt3");
  274.    }
  275.  
  276.    free((void *) tempImage);
  277.  
  278.    return GL_TRUE;
  279. }
  280.  
  281.  
  282. /**
  283.  * Store user's image in rgba_dxt5 format.
  284.  */
  285. GLboolean
  286. _mesa_texstore_rgba_dxt5(TEXSTORE_PARAMS)
  287. {
  288.    const GLubyte *pixels;
  289.    GLubyte *dst;
  290.    const GLubyte *tempImage = NULL;
  291.  
  292.    ASSERT(dstFormat == MESA_FORMAT_RGBA_DXT5 ||
  293.           dstFormat == MESA_FORMAT_SRGBA_DXT5);
  294.  
  295.    if (srcFormat != GL_RGBA ||
  296.        srcType != GL_UNSIGNED_BYTE ||
  297.        ctx->_ImageTransferState ||
  298.        srcPacking->RowLength != srcWidth ||
  299.        srcPacking->SwapBytes) {
  300.       /* convert image to RGBA/GLubyte */
  301.       tempImage = _mesa_make_temp_ubyte_image(ctx, dims,
  302.                                              baseInternalFormat,
  303.                                              _mesa_get_format_base_format(dstFormat),
  304.                                              srcWidth, srcHeight, srcDepth,
  305.                                              srcFormat, srcType, srcAddr,
  306.                                              srcPacking);
  307.       if (!tempImage)
  308.          return GL_FALSE; /* out of memory */
  309.       pixels = tempImage;
  310.    }
  311.    else {
  312.       pixels = _mesa_image_address2d(srcPacking, srcAddr, srcWidth, srcHeight,
  313.                                      srcFormat, srcType, 0, 0);
  314.    }
  315.  
  316.    dst = dstSlices[0];
  317.  
  318.    if (ext_tx_compress_dxtn) {
  319.       (*ext_tx_compress_dxtn)(4, srcWidth, srcHeight, pixels,
  320.                               GL_COMPRESSED_RGBA_S3TC_DXT5_EXT,
  321.                               dst, dstRowStride);
  322.    }
  323.    else {
  324.       _mesa_warning(ctx, "external dxt library not available: texstore_rgba_dxt5");
  325.    }
  326.  
  327.    free((void *) tempImage);
  328.  
  329.    return GL_TRUE;
  330. }
  331.  
  332.  
  333. /** Report problem with dxt texture decompression, once */
  334. static void
  335. problem(const char *func)
  336. {
  337.    static GLboolean warned = GL_FALSE;
  338.    if (!warned) {
  339.       _mesa_debug(NULL, "attempted to decode DXT texture without "
  340.                   "library available: %s\n", func);
  341.       warned = GL_TRUE;
  342.    }
  343. }
  344.  
  345.  
  346. static void
  347. fetch_rgb_dxt1(const GLubyte *map,
  348.                GLint rowStride, GLint i, GLint j, GLfloat *texel)
  349. {
  350.    if (fetch_ext_rgb_dxt1) {
  351.       GLubyte tex[4];
  352.       fetch_ext_rgb_dxt1(rowStride, map, i, j, tex);
  353.       texel[RCOMP] = UBYTE_TO_FLOAT(tex[RCOMP]);
  354.       texel[GCOMP] = UBYTE_TO_FLOAT(tex[GCOMP]);
  355.       texel[BCOMP] = UBYTE_TO_FLOAT(tex[BCOMP]);
  356.       texel[ACOMP] = UBYTE_TO_FLOAT(tex[ACOMP]);
  357.    }
  358.    else {
  359.       problem("rgb_dxt1");
  360.    }
  361. }
  362.  
  363. static void
  364. fetch_rgba_dxt1(const GLubyte *map,
  365.                 GLint rowStride, GLint i, GLint j, GLfloat *texel)
  366. {
  367.    if (fetch_ext_rgba_dxt1) {
  368.       GLubyte tex[4];
  369.       fetch_ext_rgba_dxt1(rowStride, map, i, j, tex);
  370.       texel[RCOMP] = UBYTE_TO_FLOAT(tex[RCOMP]);
  371.       texel[GCOMP] = UBYTE_TO_FLOAT(tex[GCOMP]);
  372.       texel[BCOMP] = UBYTE_TO_FLOAT(tex[BCOMP]);
  373.       texel[ACOMP] = UBYTE_TO_FLOAT(tex[ACOMP]);
  374.    }
  375.    else {
  376.       problem("rgba_dxt1");
  377.    }
  378. }
  379.  
  380. static void
  381. fetch_rgba_dxt3(const GLubyte *map,
  382.                 GLint rowStride, GLint i, GLint j, GLfloat *texel)
  383. {
  384.    if (fetch_ext_rgba_dxt3) {
  385.       GLubyte tex[4];
  386.       fetch_ext_rgba_dxt3(rowStride, map, i, j, tex);
  387.       texel[RCOMP] = UBYTE_TO_FLOAT(tex[RCOMP]);
  388.       texel[GCOMP] = UBYTE_TO_FLOAT(tex[GCOMP]);
  389.       texel[BCOMP] = UBYTE_TO_FLOAT(tex[BCOMP]);
  390.       texel[ACOMP] = UBYTE_TO_FLOAT(tex[ACOMP]);
  391.    }
  392.    else {
  393.       problem("rgba_dxt3");
  394.    }
  395. }
  396.  
  397. static void
  398. fetch_rgba_dxt5(const GLubyte *map,
  399.                 GLint rowStride, GLint i, GLint j, GLfloat *texel)
  400. {
  401.    if (fetch_ext_rgba_dxt5) {
  402.       GLubyte tex[4];
  403.       fetch_ext_rgba_dxt5(rowStride, map, i, j, tex);
  404.       texel[RCOMP] = UBYTE_TO_FLOAT(tex[RCOMP]);
  405.       texel[GCOMP] = UBYTE_TO_FLOAT(tex[GCOMP]);
  406.       texel[BCOMP] = UBYTE_TO_FLOAT(tex[BCOMP]);
  407.       texel[ACOMP] = UBYTE_TO_FLOAT(tex[ACOMP]);
  408.    }
  409.    else {
  410.       problem("rgba_dxt5");
  411.    }
  412. }
  413.  
  414.  
  415. static void
  416. fetch_srgb_dxt1(const GLubyte *map,
  417.                 GLint rowStride, GLint i, GLint j, GLfloat *texel)
  418. {
  419.    if (fetch_ext_rgb_dxt1) {
  420.       GLubyte tex[4];
  421.       fetch_ext_rgb_dxt1(rowStride, map, i, j, tex);
  422.       texel[RCOMP] = _mesa_nonlinear_to_linear(tex[RCOMP]);
  423.       texel[GCOMP] = _mesa_nonlinear_to_linear(tex[GCOMP]);
  424.       texel[BCOMP] = _mesa_nonlinear_to_linear(tex[BCOMP]);
  425.       texel[ACOMP] = UBYTE_TO_FLOAT(tex[ACOMP]);
  426.    }
  427.    else {
  428.       problem("srgb_dxt1");
  429.    }
  430. }
  431.  
  432. static void
  433. fetch_srgba_dxt1(const GLubyte *map,
  434.                  GLint rowStride, GLint i, GLint j, GLfloat *texel)
  435. {
  436.    if (fetch_ext_rgba_dxt1) {
  437.       GLubyte tex[4];
  438.       fetch_ext_rgba_dxt1(rowStride, map, i, j, tex);
  439.       texel[RCOMP] = _mesa_nonlinear_to_linear(tex[RCOMP]);
  440.       texel[GCOMP] = _mesa_nonlinear_to_linear(tex[GCOMP]);
  441.       texel[BCOMP] = _mesa_nonlinear_to_linear(tex[BCOMP]);
  442.       texel[ACOMP] = UBYTE_TO_FLOAT(tex[ACOMP]);
  443.    }
  444.    else {
  445.       problem("srgba_dxt1");
  446.    }
  447. }
  448.  
  449. static void
  450. fetch_srgba_dxt3(const GLubyte *map,
  451.                  GLint rowStride, GLint i, GLint j, GLfloat *texel)
  452. {
  453.    if (fetch_ext_rgba_dxt3) {
  454.       GLubyte tex[4];
  455.       fetch_ext_rgba_dxt3(rowStride, map, i, j, tex);
  456.       texel[RCOMP] = _mesa_nonlinear_to_linear(tex[RCOMP]);
  457.       texel[GCOMP] = _mesa_nonlinear_to_linear(tex[GCOMP]);
  458.       texel[BCOMP] = _mesa_nonlinear_to_linear(tex[BCOMP]);
  459.       texel[ACOMP] = UBYTE_TO_FLOAT(tex[ACOMP]);
  460.    }
  461.    else {
  462.       problem("srgba_dxt3");
  463.    }
  464. }
  465.  
  466. static void
  467. fetch_srgba_dxt5(const GLubyte *map,
  468.                  GLint rowStride, GLint i, GLint j, GLfloat *texel)
  469. {
  470.    if (fetch_ext_rgba_dxt5) {
  471.       GLubyte tex[4];
  472.       fetch_ext_rgba_dxt5(rowStride, map, i, j, tex);
  473.       texel[RCOMP] = _mesa_nonlinear_to_linear(tex[RCOMP]);
  474.       texel[GCOMP] = _mesa_nonlinear_to_linear(tex[GCOMP]);
  475.       texel[BCOMP] = _mesa_nonlinear_to_linear(tex[BCOMP]);
  476.       texel[ACOMP] = UBYTE_TO_FLOAT(tex[ACOMP]);
  477.    }
  478.    else {
  479.       problem("srgba_dxt5");
  480.    }
  481. }
  482.  
  483.  
  484.  
  485. compressed_fetch_func
  486. _mesa_get_dxt_fetch_func(gl_format format)
  487. {
  488.    switch (format) {
  489.    case MESA_FORMAT_RGB_DXT1:
  490.       return fetch_rgb_dxt1;
  491.    case MESA_FORMAT_RGBA_DXT1:
  492.       return fetch_rgba_dxt1;
  493.    case MESA_FORMAT_RGBA_DXT3:
  494.       return fetch_rgba_dxt3;
  495.    case MESA_FORMAT_RGBA_DXT5:
  496.       return fetch_rgba_dxt5;
  497.    case MESA_FORMAT_SRGB_DXT1:
  498.       return fetch_srgb_dxt1;
  499.    case MESA_FORMAT_SRGBA_DXT1:
  500.       return fetch_srgba_dxt1;
  501.    case MESA_FORMAT_SRGBA_DXT3:
  502.       return fetch_srgba_dxt3;
  503.    case MESA_FORMAT_SRGBA_DXT5:
  504.       return fetch_srgba_dxt5;
  505.    default:
  506.       return NULL;
  507.    }
  508. }
  509.