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  *
     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 #include <stdio.h>
     46 #include <stdarg.h>
     47 #include "c99_math.h"
     48 #include "util/rounding.h" /* for _mesa_roundeven */
     49 #include "imports.h"
     50 #include "context.h"
     51 #include "mtypes.h"
     52 #include "version.h"
     53 
     54 #ifdef _GNU_SOURCE
     55 #include <locale.h>
     56 #ifdef __APPLE__
     57 #include <xlocale.h>
     58 #endif
     59 #endif
     60 
     61 
     62 #ifdef _WIN32
     63 #define vsnprintf _vsnprintf
     64 #elif defined(__IBMC__) || defined(__IBMCPP__)
     65 extern int vsnprintf(char *str, size_t count, const char *fmt, va_list arg);
     66 #endif
     67 
     68 /**********************************************************************/
     69 /** \name Memory */
     70 /*@{*/
     71 
     72 /**
     73  * Allocate aligned memory.
     74  *
     75  * \param bytes number of bytes to allocate.
     76  * \param alignment alignment (must be greater than zero).
     77  *
     78  * Allocates extra memory to accommodate rounding up the address for
     79  * alignment and to record the real malloc address.
     80  *
     81  * \sa _mesa_align_free().
     82  */
     83 void *
     84 _mesa_align_malloc(size_t bytes, unsigned long alignment)
     85 {
     86 #if defined(HAVE_POSIX_MEMALIGN)
     87    void *mem;
     88    int err = posix_memalign(& mem, alignment, bytes);
     89    if (err)
     90       return NULL;
     91    return mem;
     92 #elif defined(_WIN32)
     93    return _aligned_malloc(bytes, alignment);
     94 #else
     95    uintptr_t ptr, buf;
     96 
     97    assert( alignment > 0 );
     98 
     99    ptr = (uintptr_t)malloc(bytes + alignment + sizeof(void *));
    100    if (!ptr)
    101       return NULL;
    102 
    103    buf = (ptr + alignment + sizeof(void *)) & ~(uintptr_t)(alignment - 1);
    104    *(uintptr_t *)(buf - sizeof(void *)) = ptr;
    105 
    106 #ifdef DEBUG
    107    /* mark the non-aligned area */
    108    while ( ptr < buf - sizeof(void *) ) {
    109       *(unsigned long *)ptr = 0xcdcdcdcd;
    110       ptr += sizeof(unsigned long);
    111    }
    112 #endif
    113 
    114    return (void *) buf;
    115 #endif /* defined(HAVE_POSIX_MEMALIGN) */
    116 }
    117 
    118 /**
    119  * Same as _mesa_align_malloc(), but using calloc(1, ) instead of
    120  * malloc()
    121  */
    122 void *
    123 _mesa_align_calloc(size_t bytes, unsigned long alignment)
    124 {
    125 #if defined(HAVE_POSIX_MEMALIGN)
    126    void *mem;
    127 
    128    mem = _mesa_align_malloc(bytes, alignment);
    129    if (mem != NULL) {
    130       (void) memset(mem, 0, bytes);
    131    }
    132 
    133    return mem;
    134 #elif defined(_WIN32)
    135    void *mem;
    136 
    137    mem = _aligned_malloc(bytes, alignment);
    138    if (mem != NULL) {
    139       (void) memset(mem, 0, bytes);
    140    }
    141 
    142    return mem;
    143 #else
    144    uintptr_t ptr, buf;
    145 
    146    assert( alignment > 0 );
    147 
    148    ptr = (uintptr_t)calloc(1, bytes + alignment + sizeof(void *));
    149    if (!ptr)
    150       return NULL;
    151 
    152    buf = (ptr + alignment + sizeof(void *)) & ~(uintptr_t)(alignment - 1);
    153    *(uintptr_t *)(buf - sizeof(void *)) = ptr;
    154 
    155 #ifdef DEBUG
    156    /* mark the non-aligned area */
    157    while ( ptr < buf - sizeof(void *) ) {
    158       *(unsigned long *)ptr = 0xcdcdcdcd;
    159       ptr += sizeof(unsigned long);
    160    }
    161 #endif
    162 
    163    return (void *)buf;
    164 #endif /* defined(HAVE_POSIX_MEMALIGN) */
    165 }
    166 
    167 /**
    168  * Free memory which was allocated with either _mesa_align_malloc()
    169  * or _mesa_align_calloc().
    170  * \param ptr pointer to the memory to be freed.
    171  * The actual address to free is stored in the word immediately before the
    172  * address the client sees.
    173  * Note that it is legal to pass NULL pointer to this function and will be
    174  * handled accordingly.
    175  */
    176 void
    177 _mesa_align_free(void *ptr)
    178 {
    179 #if defined(HAVE_POSIX_MEMALIGN)
    180    free(ptr);
    181 #elif defined(_WIN32)
    182    _aligned_free(ptr);
    183 #else
    184    if (ptr) {
    185       void **cubbyHole = (void **) ((char *) ptr - sizeof(void *));
    186       void *realAddr = *cubbyHole;
    187       free(realAddr);
    188    }
    189 #endif /* defined(HAVE_POSIX_MEMALIGN) */
    190 }
    191 
    192 /**
    193  * Reallocate memory, with alignment.
    194  */
    195 void *
    196 _mesa_align_realloc(void *oldBuffer, size_t oldSize, size_t newSize,
    197                     unsigned long alignment)
    198 {
    199 #if defined(_WIN32)
    200    (void) oldSize;
    201    return _aligned_realloc(oldBuffer, newSize, alignment);
    202 #else
    203    const size_t copySize = (oldSize < newSize) ? oldSize : newSize;
    204    void *newBuf = _mesa_align_malloc(newSize, alignment);
    205    if (newBuf && oldBuffer && copySize > 0) {
    206       memcpy(newBuf, oldBuffer, copySize);
    207    }
    208 
    209    _mesa_align_free(oldBuffer);
    210    return newBuf;
    211 #endif
    212 }
    213 
    214 /*@}*/
    215 
    216 
    217 /**********************************************************************/
    218 /** \name Math */
    219 /*@{*/
    220 
    221 
    222 #ifndef HAVE___BUILTIN_POPCOUNT
    223 /**
    224  * Return number of bits set in given GLuint.
    225  */
    226 unsigned int
    227 _mesa_bitcount(unsigned int n)
    228 {
    229    unsigned int bits;
    230    for (bits = 0; n > 0; n = n >> 1) {
    231       bits += (n & 1);
    232    }
    233    return bits;
    234 }
    235 #endif
    236 
    237 #ifndef HAVE___BUILTIN_POPCOUNTLL
    238 /**
    239  * Return number of bits set in given 64-bit uint.
    240  */
    241 unsigned int
    242 _mesa_bitcount_64(uint64_t n)
    243 {
    244    unsigned int bits;
    245    for (bits = 0; n > 0; n = n >> 1) {
    246       bits += (n & 1);
    247    }
    248    return bits;
    249 }
    250 #endif
    251 
    252 /*@}*/
    253 
    254 
    255 /** Needed due to #ifdef's, above. */
    256 int
    257 _mesa_vsnprintf(char *str, size_t size, const char *fmt, va_list args)
    258 {
    259    return vsnprintf( str, size, fmt, args);
    260 }
    261 
    262 /** Wrapper around vsnprintf() */
    263 int
    264 _mesa_snprintf( char *str, size_t size, const char *fmt, ... )
    265 {
    266    int r;
    267    va_list args;
    268    va_start( args, fmt );
    269    r = vsnprintf( str, size, fmt, args );
    270    va_end( args );
    271    return r;
    272 }
    273 
    274 
    275