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