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