Subversion Repositories Kolibri OS

Rev

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

  1. /**
  2.  * \file imports.c
  3.  * Standard C library function wrappers.
  4.  *
  5.  * Imports are services which the device driver or window system or
  6.  * operating system provides to the core renderer.  The core renderer (Mesa)
  7.  * will call these functions in order to do memory allocation, simple I/O,
  8.  * etc.
  9.  *
  10.  * Some drivers will want to override/replace this file with something
  11.  * specialized, but that'll be rare.
  12.  *
  13.  * Eventually, I want to move roll the glheader.h file into this.
  14.  *
  15.  * \todo Functions still needed:
  16.  * - scanf
  17.  * - qsort
  18.  * - rand and RAND_MAX
  19.  */
  20.  
  21. /*
  22.  * Mesa 3-D graphics library
  23.  *
  24.  * Copyright (C) 1999-2007  Brian Paul   All Rights Reserved.
  25.  *
  26.  * Permission is hereby granted, free of charge, to any person obtaining a
  27.  * copy of this software and associated documentation files (the "Software"),
  28.  * to deal in the Software without restriction, including without limitation
  29.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  30.  * and/or sell copies of the Software, and to permit persons to whom the
  31.  * Software is furnished to do so, subject to the following conditions:
  32.  *
  33.  * The above copyright notice and this permission notice shall be included
  34.  * in all copies or substantial portions of the Software.
  35.  *
  36.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  37.  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  38.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  39.  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
  40.  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  41.  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  42.  * OTHER DEALINGS IN THE SOFTWARE.
  43.  */
  44.  
  45.  
  46.  
  47. #include "imports.h"
  48. #include "context.h"
  49. #include "mtypes.h"
  50. #include "version.h"
  51.  
  52. #ifdef _GNU_SOURCE
  53. #include <locale.h>
  54. #ifdef __APPLE__
  55. #include <xlocale.h>
  56. #endif
  57. #endif
  58.  
  59.  
  60. #ifdef _WIN32
  61. #define vsnprintf _vsnprintf
  62. #elif defined(__IBMC__) || defined(__IBMCPP__)
  63. extern int vsnprintf(char *str, size_t count, const char *fmt, va_list arg);
  64. #endif
  65.  
  66. /**********************************************************************/
  67. /** \name Memory */
  68. /*@{*/
  69.  
  70. /**
  71.  * Allocate aligned memory.
  72.  *
  73.  * \param bytes number of bytes to allocate.
  74.  * \param alignment alignment (must be greater than zero).
  75.  *
  76.  * Allocates extra memory to accommodate rounding up the address for
  77.  * alignment and to record the real malloc address.
  78.  *
  79.  * \sa _mesa_align_free().
  80.  */
  81. void *
  82. _mesa_align_malloc(size_t bytes, unsigned long alignment)
  83. {
  84. #if defined(HAVE_POSIX_MEMALIGN)
  85.    void *mem;
  86.    int err = posix_memalign(& mem, alignment, bytes);
  87.    if (err)
  88.       return NULL;
  89.    return mem;
  90. #elif defined(_WIN32) && defined(_MSC_VER)
  91.    return _aligned_malloc(bytes, alignment);
  92. #else
  93.    uintptr_t ptr, buf;
  94.  
  95.    ASSERT( alignment > 0 );
  96.  
  97.    ptr = (uintptr_t)malloc(bytes + alignment + sizeof(void *));
  98.    if (!ptr)
  99.       return NULL;
  100.  
  101.    buf = (ptr + alignment + sizeof(void *)) & ~(uintptr_t)(alignment - 1);
  102.    *(uintptr_t *)(buf - sizeof(void *)) = ptr;
  103.  
  104. #ifdef DEBUG
  105.    /* mark the non-aligned area */
  106.    while ( ptr < buf - sizeof(void *) ) {
  107.       *(unsigned long *)ptr = 0xcdcdcdcd;
  108.       ptr += sizeof(unsigned long);
  109.    }
  110. #endif
  111.  
  112.    return (void *) buf;
  113. #endif /* defined(HAVE_POSIX_MEMALIGN) */
  114. }
  115.  
  116. /**
  117.  * Same as _mesa_align_malloc(), but using calloc(1, ) instead of
  118.  * malloc()
  119.  */
  120. void *
  121. _mesa_align_calloc(size_t bytes, unsigned long alignment)
  122. {
  123. #if defined(HAVE_POSIX_MEMALIGN)
  124.    void *mem;
  125.    
  126.    mem = _mesa_align_malloc(bytes, alignment);
  127.    if (mem != NULL) {
  128.       (void) memset(mem, 0, bytes);
  129.    }
  130.  
  131.    return mem;
  132. #elif defined(_WIN32) && defined(_MSC_VER)
  133.    void *mem;
  134.  
  135.    mem = _aligned_malloc(bytes, alignment);
  136.    if (mem != NULL) {
  137.       (void) memset(mem, 0, bytes);
  138.    }
  139.  
  140.    return mem;
  141. #else
  142.    uintptr_t ptr, buf;
  143.  
  144.    ASSERT( alignment > 0 );
  145.  
  146.    ptr = (uintptr_t)calloc(1, bytes + alignment + sizeof(void *));
  147.    if (!ptr)
  148.       return NULL;
  149.  
  150.    buf = (ptr + alignment + sizeof(void *)) & ~(uintptr_t)(alignment - 1);
  151.    *(uintptr_t *)(buf - sizeof(void *)) = ptr;
  152.  
  153. #ifdef DEBUG
  154.    /* mark the non-aligned area */
  155.    while ( ptr < buf - sizeof(void *) ) {
  156.       *(unsigned long *)ptr = 0xcdcdcdcd;
  157.       ptr += sizeof(unsigned long);
  158.    }
  159. #endif
  160.  
  161.    return (void *)buf;
  162. #endif /* defined(HAVE_POSIX_MEMALIGN) */
  163. }
  164.  
  165. /**
  166.  * Free memory which was allocated with either _mesa_align_malloc()
  167.  * or _mesa_align_calloc().
  168.  * \param ptr pointer to the memory to be freed.
  169.  * The actual address to free is stored in the word immediately before the
  170.  * address the client sees.
  171.  */
  172. void
  173. _mesa_align_free(void *ptr)
  174. {
  175. #if defined(HAVE_POSIX_MEMALIGN)
  176.    free(ptr);
  177. #elif defined(_WIN32) && defined(_MSC_VER)
  178.    _aligned_free(ptr);
  179. #else
  180.    void **cubbyHole = (void **) ((char *) ptr - sizeof(void *));
  181.    void *realAddr = *cubbyHole;
  182.    free(realAddr);
  183. #endif /* defined(HAVE_POSIX_MEMALIGN) */
  184. }
  185.  
  186. /**
  187.  * Reallocate memory, with alignment.
  188.  */
  189. void *
  190. _mesa_align_realloc(void *oldBuffer, size_t oldSize, size_t newSize,
  191.                     unsigned long alignment)
  192. {
  193. #if defined(_WIN32) && defined(_MSC_VER)
  194.    (void) oldSize;
  195.    return _aligned_realloc(oldBuffer, newSize, alignment);
  196. #else
  197.    const size_t copySize = (oldSize < newSize) ? oldSize : newSize;
  198.    void *newBuf = _mesa_align_malloc(newSize, alignment);
  199.    if (newBuf && oldBuffer && copySize > 0) {
  200.       memcpy(newBuf, oldBuffer, copySize);
  201.    }
  202.    if (oldBuffer)
  203.       _mesa_align_free(oldBuffer);
  204.    return newBuf;
  205. #endif
  206. }
  207.  
  208.  
  209.  
  210. /** Reallocate memory */
  211. void *
  212. _mesa_realloc(void *oldBuffer, size_t oldSize, size_t newSize)
  213. {
  214.    const size_t copySize = (oldSize < newSize) ? oldSize : newSize;
  215.    void *newBuffer = malloc(newSize);
  216.    if (newBuffer && oldBuffer && copySize > 0)
  217.       memcpy(newBuffer, oldBuffer, copySize);
  218.    free(oldBuffer);
  219.    return newBuffer;
  220. }
  221.  
  222. /*@}*/
  223.  
  224.  
  225. /**********************************************************************/
  226. /** \name Math */
  227. /*@{*/
  228.  
  229.  
  230. #ifndef __GNUC__
  231. /**
  232.  * Find the first bit set in a word.
  233.  */
  234. int
  235. ffs(int i)
  236. {
  237.    register int bit = 0;
  238.    if (i != 0) {
  239.       if ((i & 0xffff) == 0) {
  240.          bit += 16;
  241.          i >>= 16;
  242.       }
  243.       if ((i & 0xff) == 0) {
  244.          bit += 8;
  245.          i >>= 8;
  246.       }
  247.       if ((i & 0xf) == 0) {
  248.          bit += 4;
  249.          i >>= 4;
  250.       }
  251.       while ((i & 1) == 0) {
  252.          bit++;
  253.          i >>= 1;
  254.       }
  255.       bit++;
  256.    }
  257.    return bit;
  258. }
  259.  
  260.  
  261. /**
  262.  * Find position of first bit set in given value.
  263.  * XXX Warning: this function can only be used on 64-bit systems!
  264.  * \return  position of least-significant bit set, starting at 1, return zero
  265.  *          if no bits set.
  266.  */
  267. int
  268. ffsll(long long int val)
  269. {
  270.    int bit;
  271.  
  272.    assert(sizeof(val) == 8);
  273.  
  274.    bit = ffs((int) val);
  275.    if (bit != 0)
  276.       return bit;
  277.  
  278.    bit = ffs((int) (val >> 32));
  279.    if (bit != 0)
  280.       return 32 + bit;
  281.  
  282.    return 0;
  283. }
  284. #endif /* __GNUC__ */
  285.  
  286.  
  287. #if !defined(__GNUC__) ||\
  288.    ((__GNUC__ * 100 + __GNUC_MINOR__) < 304) /* Not gcc 3.4 or later */
  289. /**
  290.  * Return number of bits set in given GLuint.
  291.  */
  292. unsigned int
  293. _mesa_bitcount(unsigned int n)
  294. {
  295.    unsigned int bits;
  296.    for (bits = 0; n > 0; n = n >> 1) {
  297.       bits += (n & 1);
  298.    }
  299.    return bits;
  300. }
  301.  
  302. /**
  303.  * Return number of bits set in given 64-bit uint.
  304.  */
  305. unsigned int
  306. _mesa_bitcount_64(uint64_t n)
  307. {
  308.    unsigned int bits;
  309.    for (bits = 0; n > 0; n = n >> 1) {
  310.       bits += (n & 1);
  311.    }
  312.    return bits;
  313. }
  314. #endif
  315.  
  316.  
  317. /* Using C99 rounding functions for roundToEven() implementation is
  318.  * difficult, because round(), rint, and nearbyint() are affected by
  319.  * fesetenv(), which the application may have done for its own
  320.  * purposes.  Mesa's IROUND macro is close to what we want, but it
  321.  * rounds away from 0 on n + 0.5.
  322.  */
  323. int
  324. _mesa_round_to_even(float val)
  325. {
  326.    int rounded = IROUND(val);
  327.  
  328.    if (val - floor(val) == 0.5) {
  329.       if (rounded % 2 != 0)
  330.          rounded += val > 0 ? -1 : 1;
  331.    }
  332.  
  333.    return rounded;
  334. }
  335.  
  336.  
  337. /**
  338.  * Convert a 4-byte float to a 2-byte half float.
  339.  *
  340.  * Not all float32 values can be represented exactly as a float16 value. We
  341.  * round such intermediate float32 values to the nearest float16. When the
  342.  * float32 lies exactly between to float16 values, we round to the one with
  343.  * an even mantissa.
  344.  *
  345.  * This rounding behavior has several benefits:
  346.  *   - It has no sign bias.
  347.  *
  348.  *   - It reproduces the behavior of real hardware: opcode F32TO16 in Intel's
  349.  *     GPU ISA.
  350.  *
  351.  *   - By reproducing the behavior of the GPU (at least on Intel hardware),
  352.  *     compile-time evaluation of constant packHalf2x16 GLSL expressions will
  353.  *     result in the same value as if the expression were executed on the GPU.
  354.  */
  355. GLhalfARB
  356. _mesa_float_to_half(float val)
  357. {
  358.    const fi_type fi = {val};
  359.    const int flt_m = fi.i & 0x7fffff;
  360.    const int flt_e = (fi.i >> 23) & 0xff;
  361.    const int flt_s = (fi.i >> 31) & 0x1;
  362.    int s, e, m = 0;
  363.    GLhalfARB result;
  364.    
  365.    /* sign bit */
  366.    s = flt_s;
  367.  
  368.    /* handle special cases */
  369.    if ((flt_e == 0) && (flt_m == 0)) {
  370.       /* zero */
  371.       /* m = 0; - already set */
  372.       e = 0;
  373.    }
  374.    else if ((flt_e == 0) && (flt_m != 0)) {
  375.       /* denorm -- denorm float maps to 0 half */
  376.       /* m = 0; - already set */
  377.       e = 0;
  378.    }
  379.    else if ((flt_e == 0xff) && (flt_m == 0)) {
  380.       /* infinity */
  381.       /* m = 0; - already set */
  382.       e = 31;
  383.    }
  384.    else if ((flt_e == 0xff) && (flt_m != 0)) {
  385.       /* NaN */
  386.       m = 1;
  387.       e = 31;
  388.    }
  389.    else {
  390.       /* regular number */
  391.       const int new_exp = flt_e - 127;
  392.       if (new_exp < -14) {
  393.          /* The float32 lies in the range (0.0, min_normal16) and is rounded
  394.           * to a nearby float16 value. The result will be either zero, subnormal,
  395.           * or normal.
  396.           */
  397.          e = 0;
  398.          m = _mesa_round_to_even((1 << 24) * fabsf(fi.f));
  399.       }
  400.       else if (new_exp > 15) {
  401.          /* map this value to infinity */
  402.          /* m = 0; - already set */
  403.          e = 31;
  404.       }
  405.       else {
  406.          /* The float32 lies in the range
  407.           *   [min_normal16, max_normal16 + max_step16)
  408.           * and is rounded to a nearby float16 value. The result will be
  409.           * either normal or infinite.
  410.           */
  411.          e = new_exp + 15;
  412.          m = _mesa_round_to_even(flt_m / (float) (1 << 13));
  413.       }
  414.    }
  415.  
  416.    assert(0 <= m && m <= 1024);
  417.    if (m == 1024) {
  418.       /* The float32 was rounded upwards into the range of the next exponent,
  419.        * so bump the exponent. This correctly handles the case where f32
  420.        * should be rounded up to float16 infinity.
  421.        */
  422.       ++e;
  423.       m = 0;
  424.    }
  425.  
  426.    result = (s << 15) | (e << 10) | m;
  427.    return result;
  428. }
  429.  
  430.  
  431. /**
  432.  * Convert a 2-byte half float to a 4-byte float.
  433.  * Based on code from:
  434.  * http://www.opengl.org/discussion_boards/ubb/Forum3/HTML/008786.html
  435.  */
  436. float
  437. _mesa_half_to_float(GLhalfARB val)
  438. {
  439.    /* XXX could also use a 64K-entry lookup table */
  440.    const int m = val & 0x3ff;
  441.    const int e = (val >> 10) & 0x1f;
  442.    const int s = (val >> 15) & 0x1;
  443.    int flt_m, flt_e, flt_s;
  444.    fi_type fi;
  445.    float result;
  446.  
  447.    /* sign bit */
  448.    flt_s = s;
  449.  
  450.    /* handle special cases */
  451.    if ((e == 0) && (m == 0)) {
  452.       /* zero */
  453.       flt_m = 0;
  454.       flt_e = 0;
  455.    }
  456.    else if ((e == 0) && (m != 0)) {
  457.       /* denorm -- denorm half will fit in non-denorm single */
  458.       const float half_denorm = 1.0f / 16384.0f; /* 2^-14 */
  459.       float mantissa = ((float) (m)) / 1024.0f;
  460.       float sign = s ? -1.0f : 1.0f;
  461.       return sign * mantissa * half_denorm;
  462.    }
  463.    else if ((e == 31) && (m == 0)) {
  464.       /* infinity */
  465.       flt_e = 0xff;
  466.       flt_m = 0;
  467.    }
  468.    else if ((e == 31) && (m != 0)) {
  469.       /* NaN */
  470.       flt_e = 0xff;
  471.       flt_m = 1;
  472.    }
  473.    else {
  474.       /* regular */
  475.       flt_e = e + 112;
  476.       flt_m = m << 13;
  477.    }
  478.  
  479.    fi.i = (flt_s << 31) | (flt_e << 23) | flt_m;
  480.    result = fi.f;
  481.    return result;
  482. }
  483.  
  484. /*@}*/
  485.  
  486.  
  487. /**********************************************************************/
  488. /** \name Sort & Search */
  489. /*@{*/
  490.  
  491. /**
  492.  * Wrapper for bsearch().
  493.  */
  494. void *
  495. _mesa_bsearch( const void *key, const void *base, size_t nmemb, size_t size,
  496.                int (*compar)(const void *, const void *) )
  497. {
  498. #if defined(_WIN32_WCE)
  499.    void *mid;
  500.    int cmp;
  501.    while (nmemb) {
  502.       nmemb >>= 1;
  503.       mid = (char *)base + nmemb * size;
  504.       cmp = (*compar)(key, mid);
  505.       if (cmp == 0)
  506.          return mid;
  507.       if (cmp > 0) {
  508.          base = (char *)mid + size;
  509.          --nmemb;
  510.       }
  511.    }
  512.    return NULL;
  513. #else
  514.    return bsearch(key, base, nmemb, size, compar);
  515. #endif
  516. }
  517.  
  518. /*@}*/
  519.  
  520.  
  521. /**********************************************************************/
  522. /** \name Environment vars */
  523. /*@{*/
  524.  
  525. /**
  526.  * Wrapper for getenv().
  527.  */
  528. char *
  529. _mesa_getenv( const char *var )
  530. {
  531. #if defined(_XBOX) || defined(_WIN32_WCE)
  532.    return NULL;
  533. #else
  534.    return getenv(var);
  535. #endif
  536. }
  537.  
  538. /*@}*/
  539.  
  540.  
  541. /**********************************************************************/
  542. /** \name String */
  543. /*@{*/
  544.  
  545. /**
  546.  * Implemented using malloc() and strcpy.
  547.  * Note that NULL is handled accordingly.
  548.  */
  549. char *
  550. _mesa_strdup( const char *s )
  551. {
  552.    if (s) {
  553.       size_t l = strlen(s);
  554.       char *s2 = malloc(l + 1);
  555.       if (s2)
  556.          strcpy(s2, s);
  557.       return s2;
  558.    }
  559.    else {
  560.       return NULL;
  561.    }
  562. }
  563.  
  564. /** Wrapper around strtof() */
  565. float
  566. _mesa_strtof( const char *s, char **end )
  567. {
  568. #if defined(_GNU_SOURCE) && !defined(__CYGWIN__) && !defined(__FreeBSD__) && \
  569.    !defined(ANDROID) && !defined(__HAIKU__) && !defined(__UCLIBC__)
  570.    static locale_t loc = NULL;
  571.    if (!loc) {
  572.       loc = newlocale(LC_CTYPE_MASK, "C", NULL);
  573.    }
  574.    return strtof_l(s, end, loc);
  575. #elif defined(_ISOC99_SOURCE) || (defined(_XOPEN_SOURCE) && _XOPEN_SOURCE >= 600)
  576.    return strtof(s, end);
  577. #else
  578.    return (float)strtod(s, end);
  579. #endif
  580. }
  581.  
  582. /** Compute simple checksum/hash for a string */
  583. unsigned int
  584. _mesa_str_checksum(const char *str)
  585. {
  586.    /* This could probably be much better */
  587.    unsigned int sum, i;
  588.    const char *c;
  589.    sum = i = 1;
  590.    for (c = str; *c; c++, i++)
  591.       sum += *c * (i % 100);
  592.    return sum + i;
  593. }
  594.  
  595.  
  596. /*@}*/
  597.  
  598.  
  599. /** Needed due to #ifdef's, above. */
  600. int
  601. _mesa_vsnprintf(char *str, size_t size, const char *fmt, va_list args)
  602. {
  603.    return vsnprintf( str, size, fmt, args);
  604. }
  605.  
  606. /** Wrapper around vsnprintf() */
  607. int
  608. _mesa_snprintf( char *str, size_t size, const char *fmt, ... )
  609. {
  610.    int r;
  611.    va_list args;
  612.    va_start( args, fmt );  
  613.    r = vsnprintf( str, size, fmt, args );
  614.    va_end( args );
  615.    return r;
  616. }
  617.  
  618.  
  619.