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