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. #include "glheader.h"
  33. #include "imports.h"
  34. #include "dlopen.h"
  35. #include "image.h"
  36. #include "macros.h"
  37. #include "mtypes.h"
  38. #include "texcompress.h"
  39. #include "texcompress_s3tc.h"
  40. #include "texstore.h"
  41. #include "format_unpack.h"
  42. #include "util/format_srgb.h"
  43.  
  44.  
  45. #if defined(_WIN32) || defined(WIN32)
  46. #define DXTN_LIBNAME "dxtn.dll"
  47. #define RTLD_LAZY 0
  48. #define RTLD_GLOBAL 0
  49. #else
  50. #define DXTN_LIBNAME "libtxc_dxtn.so"
  51. #endif
  52.  
  53. typedef void (*dxtFetchTexelFuncExt)( GLint srcRowstride, const GLubyte *pixdata, GLint col, GLint row, GLvoid *texelOut );
  54.  
  55. static dxtFetchTexelFuncExt fetch_ext_rgb_dxt1 = NULL;
  56. static dxtFetchTexelFuncExt fetch_ext_rgba_dxt1 = NULL;
  57. static dxtFetchTexelFuncExt fetch_ext_rgba_dxt3 = NULL;
  58. static dxtFetchTexelFuncExt fetch_ext_rgba_dxt5 = NULL;
  59.  
  60. typedef void (*dxtCompressTexFuncExt)(GLint srccomps, GLint width,
  61.                                       GLint height, const GLubyte *srcPixData,
  62.                                       GLenum destformat, GLubyte *dest,
  63.                                       GLint dstRowStride);
  64.  
  65. static dxtCompressTexFuncExt ext_tx_compress_dxtn = NULL;
  66.  
  67. static void *dxtlibhandle = NULL;
  68.  
  69.  
  70. void
  71. _mesa_init_texture_s3tc( struct gl_context *ctx )
  72. {
  73.    /* called during context initialization */
  74.    ctx->Mesa_DXTn = GL_FALSE;
  75.    if (!dxtlibhandle) {
  76.       dxtlibhandle = _mesa_dlopen(DXTN_LIBNAME, 0);
  77.       if (!dxtlibhandle) {
  78.          _mesa_warning(ctx, "couldn't open " DXTN_LIBNAME ", software DXTn "
  79.             "compression/decompression unavailable");
  80.       }
  81.       else {
  82.          /* the fetch functions are not per context! Might be problematic... */
  83.          fetch_ext_rgb_dxt1 = (dxtFetchTexelFuncExt)
  84.             _mesa_dlsym(dxtlibhandle, "fetch_2d_texel_rgb_dxt1");
  85.          fetch_ext_rgba_dxt1 = (dxtFetchTexelFuncExt)
  86.             _mesa_dlsym(dxtlibhandle, "fetch_2d_texel_rgba_dxt1");
  87.          fetch_ext_rgba_dxt3 = (dxtFetchTexelFuncExt)
  88.             _mesa_dlsym(dxtlibhandle, "fetch_2d_texel_rgba_dxt3");
  89.          fetch_ext_rgba_dxt5 = (dxtFetchTexelFuncExt)
  90.             _mesa_dlsym(dxtlibhandle, "fetch_2d_texel_rgba_dxt5");
  91.          ext_tx_compress_dxtn = (dxtCompressTexFuncExt)
  92.             _mesa_dlsym(dxtlibhandle, "tx_compress_dxtn");
  93.  
  94.          if (!fetch_ext_rgb_dxt1 ||
  95.              !fetch_ext_rgba_dxt1 ||
  96.              !fetch_ext_rgba_dxt3 ||
  97.              !fetch_ext_rgba_dxt5 ||
  98.              !ext_tx_compress_dxtn) {
  99.             _mesa_warning(ctx, "couldn't reference all symbols in "
  100.                DXTN_LIBNAME ", software DXTn compression/decompression "
  101.                "unavailable");
  102.             fetch_ext_rgb_dxt1 = NULL;
  103.             fetch_ext_rgba_dxt1 = NULL;
  104.             fetch_ext_rgba_dxt3 = NULL;
  105.             fetch_ext_rgba_dxt5 = NULL;
  106.             ext_tx_compress_dxtn = NULL;
  107.             _mesa_dlclose(dxtlibhandle);
  108.             dxtlibhandle = NULL;
  109.          }
  110.       }
  111.    }
  112.    if (dxtlibhandle) {
  113.       ctx->Mesa_DXTn = GL_TRUE;
  114.    }
  115. }
  116.  
  117. /**
  118.  * Store user's image in rgb_dxt1 format.
  119.  */
  120. GLboolean
  121. _mesa_texstore_rgb_dxt1(TEXSTORE_PARAMS)
  122. {
  123.    const GLubyte *pixels;
  124.    GLubyte *dst;
  125.    const GLubyte *tempImage = NULL;
  126.  
  127.    assert(dstFormat == MESA_FORMAT_RGB_DXT1 ||
  128.           dstFormat == MESA_FORMAT_SRGB_DXT1);
  129.  
  130.    if (srcFormat != GL_RGB ||
  131.        srcType != GL_UNSIGNED_BYTE ||
  132.        ctx->_ImageTransferState ||
  133.        srcPacking->RowLength != srcWidth ||
  134.        srcPacking->SwapBytes) {
  135.       /* convert image to RGB/GLubyte */
  136.       GLubyte *tempImageSlices[1];
  137.       int rgbRowStride = 3 * srcWidth * sizeof(GLubyte);
  138.       tempImage = malloc(srcWidth * srcHeight * 3 * sizeof(GLubyte));
  139.       if (!tempImage)
  140.          return GL_FALSE; /* out of memory */
  141.       tempImageSlices[0] = (GLubyte *) tempImage;
  142.       _mesa_texstore(ctx, dims,
  143.                      baseInternalFormat,
  144.                      MESA_FORMAT_RGB_UNORM8,
  145.                      rgbRowStride, tempImageSlices,
  146.                      srcWidth, srcHeight, srcDepth,
  147.                      srcFormat, srcType, srcAddr,
  148.                      srcPacking);
  149.       pixels = tempImage;
  150.       srcFormat = GL_RGB;
  151.    }
  152.    else {
  153.       pixels = _mesa_image_address2d(srcPacking, srcAddr, srcWidth, srcHeight,
  154.                                      srcFormat, srcType, 0, 0);
  155.    }
  156.  
  157.    dst = dstSlices[0];
  158.  
  159.    if (ext_tx_compress_dxtn) {
  160.       (*ext_tx_compress_dxtn)(3, srcWidth, srcHeight, pixels,
  161.                               GL_COMPRESSED_RGB_S3TC_DXT1_EXT,
  162.                               dst, dstRowStride);
  163.    }
  164.    else {
  165.       _mesa_warning(ctx, "external dxt library not available: texstore_rgb_dxt1");
  166.    }
  167.  
  168.    free((void *) tempImage);
  169.  
  170.    return GL_TRUE;
  171. }
  172.  
  173.  
  174. /**
  175.  * Store user's image in rgba_dxt1 format.
  176.  */
  177. GLboolean
  178. _mesa_texstore_rgba_dxt1(TEXSTORE_PARAMS)
  179. {
  180.    const GLubyte *pixels;
  181.    GLubyte *dst;
  182.    const GLubyte *tempImage = NULL;
  183.  
  184.    assert(dstFormat == MESA_FORMAT_RGBA_DXT1 ||
  185.           dstFormat == MESA_FORMAT_SRGBA_DXT1);
  186.  
  187.    if (srcFormat != GL_RGBA ||
  188.        srcType != GL_UNSIGNED_BYTE ||
  189.        ctx->_ImageTransferState ||
  190.        srcPacking->RowLength != srcWidth ||
  191.        srcPacking->SwapBytes) {
  192.       /* convert image to RGBA/GLubyte */
  193.       GLubyte *tempImageSlices[1];
  194.       int rgbaRowStride = 4 * srcWidth * sizeof(GLubyte);
  195.       tempImage = malloc(srcWidth * srcHeight * 4 * sizeof(GLubyte));
  196.       if (!tempImage)
  197.          return GL_FALSE; /* out of memory */
  198.       tempImageSlices[0] = (GLubyte *) tempImage;
  199.       _mesa_texstore(ctx, dims,
  200.                      baseInternalFormat,
  201.                      MESA_FORMAT_R8G8B8A8_UNORM,
  202.                      rgbaRowStride, tempImageSlices,
  203.                      srcWidth, srcHeight, srcDepth,
  204.                      srcFormat, srcType, srcAddr,
  205.                      srcPacking);
  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.       GLubyte *tempImageSlices[1];
  251.       int rgbaRowStride = 4 * srcWidth * sizeof(GLubyte);
  252.       tempImage = malloc(srcWidth * srcHeight * 4 * sizeof(GLubyte));
  253.       if (!tempImage)
  254.          return GL_FALSE; /* out of memory */
  255.       tempImageSlices[0] = (GLubyte *) tempImage;
  256.       _mesa_texstore(ctx, dims,
  257.                      baseInternalFormat,
  258.                      MESA_FORMAT_R8G8B8A8_UNORM,
  259.                      rgbaRowStride, tempImageSlices,
  260.                      srcWidth, srcHeight, srcDepth,
  261.                      srcFormat, srcType, srcAddr,
  262.                      srcPacking);
  263.       pixels = tempImage;
  264.    }
  265.    else {
  266.       pixels = _mesa_image_address2d(srcPacking, srcAddr, srcWidth, srcHeight,
  267.                                      srcFormat, srcType, 0, 0);
  268.    }
  269.  
  270.    dst = dstSlices[0];
  271.  
  272.    if (ext_tx_compress_dxtn) {
  273.       (*ext_tx_compress_dxtn)(4, srcWidth, srcHeight, pixels,
  274.                               GL_COMPRESSED_RGBA_S3TC_DXT3_EXT,
  275.                               dst, dstRowStride);
  276.    }
  277.    else {
  278.       _mesa_warning(ctx, "external dxt library not available: texstore_rgba_dxt3");
  279.    }
  280.  
  281.    free((void *) tempImage);
  282.  
  283.    return GL_TRUE;
  284. }
  285.  
  286.  
  287. /**
  288.  * Store user's image in rgba_dxt5 format.
  289.  */
  290. GLboolean
  291. _mesa_texstore_rgba_dxt5(TEXSTORE_PARAMS)
  292. {
  293.    const GLubyte *pixels;
  294.    GLubyte *dst;
  295.    const GLubyte *tempImage = NULL;
  296.  
  297.    assert(dstFormat == MESA_FORMAT_RGBA_DXT5 ||
  298.           dstFormat == MESA_FORMAT_SRGBA_DXT5);
  299.  
  300.    if (srcFormat != GL_RGBA ||
  301.        srcType != GL_UNSIGNED_BYTE ||
  302.        ctx->_ImageTransferState ||
  303.        srcPacking->RowLength != srcWidth ||
  304.        srcPacking->SwapBytes) {
  305.       /* convert image to RGBA/GLubyte */
  306.       GLubyte *tempImageSlices[1];
  307.       int rgbaRowStride = 4 * srcWidth * sizeof(GLubyte);
  308.       tempImage = malloc(srcWidth * srcHeight * 4 * sizeof(GLubyte));
  309.       if (!tempImage)
  310.          return GL_FALSE; /* out of memory */
  311.       tempImageSlices[0] = (GLubyte *) tempImage;
  312.       _mesa_texstore(ctx, dims,
  313.                      baseInternalFormat,
  314.                      MESA_FORMAT_R8G8B8A8_UNORM,
  315.                      rgbaRowStride, tempImageSlices,
  316.                      srcWidth, srcHeight, srcDepth,
  317.                      srcFormat, srcType, srcAddr,
  318.                      srcPacking);
  319.       pixels = tempImage;
  320.    }
  321.    else {
  322.       pixels = _mesa_image_address2d(srcPacking, srcAddr, srcWidth, srcHeight,
  323.                                      srcFormat, srcType, 0, 0);
  324.    }
  325.  
  326.    dst = dstSlices[0];
  327.  
  328.    if (ext_tx_compress_dxtn) {
  329.       (*ext_tx_compress_dxtn)(4, srcWidth, srcHeight, pixels,
  330.                               GL_COMPRESSED_RGBA_S3TC_DXT5_EXT,
  331.                               dst, dstRowStride);
  332.    }
  333.    else {
  334.       _mesa_warning(ctx, "external dxt library not available: texstore_rgba_dxt5");
  335.    }
  336.  
  337.    free((void *) tempImage);
  338.  
  339.    return GL_TRUE;
  340. }
  341.  
  342.  
  343. /** Report problem with dxt texture decompression, once */
  344. static void
  345. problem(const char *func)
  346. {
  347.    static GLboolean warned = GL_FALSE;
  348.    if (!warned) {
  349.       _mesa_debug(NULL, "attempted to decode DXT texture without "
  350.                   "library available: %s\n", func);
  351.       warned = GL_TRUE;
  352.    }
  353. }
  354.  
  355.  
  356. static void
  357. fetch_rgb_dxt1(const GLubyte *map,
  358.                GLint rowStride, GLint i, GLint j, GLfloat *texel)
  359. {
  360.    if (fetch_ext_rgb_dxt1) {
  361.       GLubyte tex[4];
  362.       fetch_ext_rgb_dxt1(rowStride, map, i, j, tex);
  363.       texel[RCOMP] = UBYTE_TO_FLOAT(tex[RCOMP]);
  364.       texel[GCOMP] = UBYTE_TO_FLOAT(tex[GCOMP]);
  365.       texel[BCOMP] = UBYTE_TO_FLOAT(tex[BCOMP]);
  366.       texel[ACOMP] = UBYTE_TO_FLOAT(tex[ACOMP]);
  367.    }
  368.    else {
  369.       problem("rgb_dxt1");
  370.    }
  371. }
  372.  
  373. static void
  374. fetch_rgba_dxt1(const GLubyte *map,
  375.                 GLint rowStride, GLint i, GLint j, GLfloat *texel)
  376. {
  377.    if (fetch_ext_rgba_dxt1) {
  378.       GLubyte tex[4];
  379.       fetch_ext_rgba_dxt1(rowStride, map, i, j, tex);
  380.       texel[RCOMP] = UBYTE_TO_FLOAT(tex[RCOMP]);
  381.       texel[GCOMP] = UBYTE_TO_FLOAT(tex[GCOMP]);
  382.       texel[BCOMP] = UBYTE_TO_FLOAT(tex[BCOMP]);
  383.       texel[ACOMP] = UBYTE_TO_FLOAT(tex[ACOMP]);
  384.    }
  385.    else {
  386.       problem("rgba_dxt1");
  387.    }
  388. }
  389.  
  390. static void
  391. fetch_rgba_dxt3(const GLubyte *map,
  392.                 GLint rowStride, GLint i, GLint j, GLfloat *texel)
  393. {
  394.    if (fetch_ext_rgba_dxt3) {
  395.       GLubyte tex[4];
  396.       fetch_ext_rgba_dxt3(rowStride, map, i, j, tex);
  397.       texel[RCOMP] = UBYTE_TO_FLOAT(tex[RCOMP]);
  398.       texel[GCOMP] = UBYTE_TO_FLOAT(tex[GCOMP]);
  399.       texel[BCOMP] = UBYTE_TO_FLOAT(tex[BCOMP]);
  400.       texel[ACOMP] = UBYTE_TO_FLOAT(tex[ACOMP]);
  401.    }
  402.    else {
  403.       problem("rgba_dxt3");
  404.    }
  405. }
  406.  
  407. static void
  408. fetch_rgba_dxt5(const GLubyte *map,
  409.                 GLint rowStride, GLint i, GLint j, GLfloat *texel)
  410. {
  411.    if (fetch_ext_rgba_dxt5) {
  412.       GLubyte tex[4];
  413.       fetch_ext_rgba_dxt5(rowStride, map, i, j, tex);
  414.       texel[RCOMP] = UBYTE_TO_FLOAT(tex[RCOMP]);
  415.       texel[GCOMP] = UBYTE_TO_FLOAT(tex[GCOMP]);
  416.       texel[BCOMP] = UBYTE_TO_FLOAT(tex[BCOMP]);
  417.       texel[ACOMP] = UBYTE_TO_FLOAT(tex[ACOMP]);
  418.    }
  419.    else {
  420.       problem("rgba_dxt5");
  421.    }
  422. }
  423.  
  424.  
  425. static void
  426. fetch_srgb_dxt1(const GLubyte *map,
  427.                 GLint rowStride, GLint i, GLint j, GLfloat *texel)
  428. {
  429.    if (fetch_ext_rgb_dxt1) {
  430.       GLubyte tex[4];
  431.       fetch_ext_rgb_dxt1(rowStride, map, i, j, tex);
  432.       texel[RCOMP] = util_format_srgb_8unorm_to_linear_float(tex[RCOMP]);
  433.       texel[GCOMP] = util_format_srgb_8unorm_to_linear_float(tex[GCOMP]);
  434.       texel[BCOMP] = util_format_srgb_8unorm_to_linear_float(tex[BCOMP]);
  435.       texel[ACOMP] = UBYTE_TO_FLOAT(tex[ACOMP]);
  436.    }
  437.    else {
  438.       problem("srgb_dxt1");
  439.    }
  440. }
  441.  
  442. static void
  443. fetch_srgba_dxt1(const GLubyte *map,
  444.                  GLint rowStride, GLint i, GLint j, GLfloat *texel)
  445. {
  446.    if (fetch_ext_rgba_dxt1) {
  447.       GLubyte tex[4];
  448.       fetch_ext_rgba_dxt1(rowStride, map, i, j, tex);
  449.       texel[RCOMP] = util_format_srgb_8unorm_to_linear_float(tex[RCOMP]);
  450.       texel[GCOMP] = util_format_srgb_8unorm_to_linear_float(tex[GCOMP]);
  451.       texel[BCOMP] = util_format_srgb_8unorm_to_linear_float(tex[BCOMP]);
  452.       texel[ACOMP] = UBYTE_TO_FLOAT(tex[ACOMP]);
  453.    }
  454.    else {
  455.       problem("srgba_dxt1");
  456.    }
  457. }
  458.  
  459. static void
  460. fetch_srgba_dxt3(const GLubyte *map,
  461.                  GLint rowStride, GLint i, GLint j, GLfloat *texel)
  462. {
  463.    if (fetch_ext_rgba_dxt3) {
  464.       GLubyte tex[4];
  465.       fetch_ext_rgba_dxt3(rowStride, map, i, j, tex);
  466.       texel[RCOMP] = util_format_srgb_8unorm_to_linear_float(tex[RCOMP]);
  467.       texel[GCOMP] = util_format_srgb_8unorm_to_linear_float(tex[GCOMP]);
  468.       texel[BCOMP] = util_format_srgb_8unorm_to_linear_float(tex[BCOMP]);
  469.       texel[ACOMP] = UBYTE_TO_FLOAT(tex[ACOMP]);
  470.    }
  471.    else {
  472.       problem("srgba_dxt3");
  473.    }
  474. }
  475.  
  476. static void
  477. fetch_srgba_dxt5(const GLubyte *map,
  478.                  GLint rowStride, GLint i, GLint j, GLfloat *texel)
  479. {
  480.    if (fetch_ext_rgba_dxt5) {
  481.       GLubyte tex[4];
  482.       fetch_ext_rgba_dxt5(rowStride, map, i, j, tex);
  483.       texel[RCOMP] = util_format_srgb_8unorm_to_linear_float(tex[RCOMP]);
  484.       texel[GCOMP] = util_format_srgb_8unorm_to_linear_float(tex[GCOMP]);
  485.       texel[BCOMP] = util_format_srgb_8unorm_to_linear_float(tex[BCOMP]);
  486.       texel[ACOMP] = UBYTE_TO_FLOAT(tex[ACOMP]);
  487.    }
  488.    else {
  489.       problem("srgba_dxt5");
  490.    }
  491. }
  492.  
  493.  
  494.  
  495. compressed_fetch_func
  496. _mesa_get_dxt_fetch_func(mesa_format format)
  497. {
  498.    switch (format) {
  499.    case MESA_FORMAT_RGB_DXT1:
  500.       return fetch_rgb_dxt1;
  501.    case MESA_FORMAT_RGBA_DXT1:
  502.       return fetch_rgba_dxt1;
  503.    case MESA_FORMAT_RGBA_DXT3:
  504.       return fetch_rgba_dxt3;
  505.    case MESA_FORMAT_RGBA_DXT5:
  506.       return fetch_rgba_dxt5;
  507.    case MESA_FORMAT_SRGB_DXT1:
  508.       return fetch_srgb_dxt1;
  509.    case MESA_FORMAT_SRGBA_DXT1:
  510.       return fetch_srgba_dxt1;
  511.    case MESA_FORMAT_SRGBA_DXT3:
  512.       return fetch_srgba_dxt3;
  513.    case MESA_FORMAT_SRGBA_DXT5:
  514.       return fetch_srgba_dxt5;
  515.    default:
  516.       return NULL;
  517.    }
  518. }
  519.