imports.c revision 848b8605
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__) 63extern 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 */ 81void * 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 */ 120void * 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 * Note that it is legal to pass NULL pointer to this function and will be 172 * handled accordingly. 173 */ 174void 175_mesa_align_free(void *ptr) 176{ 177#if defined(HAVE_POSIX_MEMALIGN) 178 free(ptr); 179#elif defined(_WIN32) && defined(_MSC_VER) 180 _aligned_free(ptr); 181#else 182 if (ptr) { 183 void **cubbyHole = (void **) ((char *) ptr - sizeof(void *)); 184 void *realAddr = *cubbyHole; 185 free(realAddr); 186 } 187#endif /* defined(HAVE_POSIX_MEMALIGN) */ 188} 189 190/** 191 * Reallocate memory, with alignment. 192 */ 193void * 194_mesa_align_realloc(void *oldBuffer, size_t oldSize, size_t newSize, 195 unsigned long alignment) 196{ 197#if defined(_WIN32) && defined(_MSC_VER) 198 (void) oldSize; 199 return _aligned_realloc(oldBuffer, newSize, alignment); 200#else 201 const size_t copySize = (oldSize < newSize) ? oldSize : newSize; 202 void *newBuf = _mesa_align_malloc(newSize, alignment); 203 if (newBuf && oldBuffer && copySize > 0) { 204 memcpy(newBuf, oldBuffer, copySize); 205 } 206 207 _mesa_align_free(oldBuffer); 208 return newBuf; 209#endif 210} 211 212 213 214/** Reallocate memory */ 215void * 216_mesa_realloc(void *oldBuffer, size_t oldSize, size_t newSize) 217{ 218 const size_t copySize = (oldSize < newSize) ? oldSize : newSize; 219 void *newBuffer = malloc(newSize); 220 if (newBuffer && oldBuffer && copySize > 0) 221 memcpy(newBuffer, oldBuffer, copySize); 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 */ 238int 239ffs(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 */ 271int 272ffsll(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 */ 296unsigned 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 */ 309unsigned 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/* Using C99 rounding functions for roundToEven() implementation is 322 * difficult, because round(), rint, and nearbyint() are affected by 323 * fesetenv(), which the application may have done for its own 324 * purposes. Mesa's IROUND macro is close to what we want, but it 325 * rounds away from 0 on n + 0.5. 326 */ 327int 328_mesa_round_to_even(float val) 329{ 330 int rounded = IROUND(val); 331 332 if (val - floor(val) == 0.5) { 333 if (rounded % 2 != 0) 334 rounded += val > 0 ? -1 : 1; 335 } 336 337 return rounded; 338} 339 340 341/** 342 * Convert a 4-byte float to a 2-byte half float. 343 * 344 * Not all float32 values can be represented exactly as a float16 value. We 345 * round such intermediate float32 values to the nearest float16. When the 346 * float32 lies exactly between to float16 values, we round to the one with 347 * an even mantissa. 348 * 349 * This rounding behavior has several benefits: 350 * - It has no sign bias. 351 * 352 * - It reproduces the behavior of real hardware: opcode F32TO16 in Intel's 353 * GPU ISA. 354 * 355 * - By reproducing the behavior of the GPU (at least on Intel hardware), 356 * compile-time evaluation of constant packHalf2x16 GLSL expressions will 357 * result in the same value as if the expression were executed on the GPU. 358 */ 359GLhalfARB 360_mesa_float_to_half(float val) 361{ 362 const fi_type fi = {val}; 363 const int flt_m = fi.i & 0x7fffff; 364 const int flt_e = (fi.i >> 23) & 0xff; 365 const int flt_s = (fi.i >> 31) & 0x1; 366 int s, e, m = 0; 367 GLhalfARB result; 368 369 /* sign bit */ 370 s = flt_s; 371 372 /* handle special cases */ 373 if ((flt_e == 0) && (flt_m == 0)) { 374 /* zero */ 375 /* m = 0; - already set */ 376 e = 0; 377 } 378 else if ((flt_e == 0) && (flt_m != 0)) { 379 /* denorm -- denorm float maps to 0 half */ 380 /* m = 0; - already set */ 381 e = 0; 382 } 383 else if ((flt_e == 0xff) && (flt_m == 0)) { 384 /* infinity */ 385 /* m = 0; - already set */ 386 e = 31; 387 } 388 else if ((flt_e == 0xff) && (flt_m != 0)) { 389 /* NaN */ 390 m = 1; 391 e = 31; 392 } 393 else { 394 /* regular number */ 395 const int new_exp = flt_e - 127; 396 if (new_exp < -14) { 397 /* The float32 lies in the range (0.0, min_normal16) and is rounded 398 * to a nearby float16 value. The result will be either zero, subnormal, 399 * or normal. 400 */ 401 e = 0; 402 m = _mesa_round_to_even((1 << 24) * fabsf(fi.f)); 403 } 404 else if (new_exp > 15) { 405 /* map this value to infinity */ 406 /* m = 0; - already set */ 407 e = 31; 408 } 409 else { 410 /* The float32 lies in the range 411 * [min_normal16, max_normal16 + max_step16) 412 * and is rounded to a nearby float16 value. The result will be 413 * either normal or infinite. 414 */ 415 e = new_exp + 15; 416 m = _mesa_round_to_even(flt_m / (float) (1 << 13)); 417 } 418 } 419 420 assert(0 <= m && m <= 1024); 421 if (m == 1024) { 422 /* The float32 was rounded upwards into the range of the next exponent, 423 * so bump the exponent. This correctly handles the case where f32 424 * should be rounded up to float16 infinity. 425 */ 426 ++e; 427 m = 0; 428 } 429 430 result = (s << 15) | (e << 10) | m; 431 return result; 432} 433 434 435/** 436 * Convert a 2-byte half float to a 4-byte float. 437 * Based on code from: 438 * http://www.opengl.org/discussion_boards/ubb/Forum3/HTML/008786.html 439 */ 440float 441_mesa_half_to_float(GLhalfARB val) 442{ 443 /* XXX could also use a 64K-entry lookup table */ 444 const int m = val & 0x3ff; 445 const int e = (val >> 10) & 0x1f; 446 const int s = (val >> 15) & 0x1; 447 int flt_m, flt_e, flt_s; 448 fi_type fi; 449 float result; 450 451 /* sign bit */ 452 flt_s = s; 453 454 /* handle special cases */ 455 if ((e == 0) && (m == 0)) { 456 /* zero */ 457 flt_m = 0; 458 flt_e = 0; 459 } 460 else if ((e == 0) && (m != 0)) { 461 /* denorm -- denorm half will fit in non-denorm single */ 462 const float half_denorm = 1.0f / 16384.0f; /* 2^-14 */ 463 float mantissa = ((float) (m)) / 1024.0f; 464 float sign = s ? -1.0f : 1.0f; 465 return sign * mantissa * half_denorm; 466 } 467 else if ((e == 31) && (m == 0)) { 468 /* infinity */ 469 flt_e = 0xff; 470 flt_m = 0; 471 } 472 else if ((e == 31) && (m != 0)) { 473 /* NaN */ 474 flt_e = 0xff; 475 flt_m = 1; 476 } 477 else { 478 /* regular */ 479 flt_e = e + 112; 480 flt_m = m << 13; 481 } 482 483 fi.i = (flt_s << 31) | (flt_e << 23) | flt_m; 484 result = fi.f; 485 return result; 486} 487 488/*@}*/ 489 490 491/**********************************************************************/ 492/** \name Sort & Search */ 493/*@{*/ 494 495/** 496 * Wrapper for bsearch(). 497 */ 498void * 499_mesa_bsearch( const void *key, const void *base, size_t nmemb, size_t size, 500 int (*compar)(const void *, const void *) ) 501{ 502#if defined(_WIN32_WCE) 503 void *mid; 504 int cmp; 505 while (nmemb) { 506 nmemb >>= 1; 507 mid = (char *)base + nmemb * size; 508 cmp = (*compar)(key, mid); 509 if (cmp == 0) 510 return mid; 511 if (cmp > 0) { 512 base = (char *)mid + size; 513 --nmemb; 514 } 515 } 516 return NULL; 517#else 518 return bsearch(key, base, nmemb, size, compar); 519#endif 520} 521 522/*@}*/ 523 524 525/**********************************************************************/ 526/** \name Environment vars */ 527/*@{*/ 528 529/** 530 * Wrapper for getenv(). 531 */ 532char * 533_mesa_getenv( const char *var ) 534{ 535#if defined(_XBOX) || defined(_WIN32_WCE) 536 return NULL; 537#else 538 return getenv(var); 539#endif 540} 541 542/*@}*/ 543 544 545/**********************************************************************/ 546/** \name String */ 547/*@{*/ 548 549/** 550 * Implemented using malloc() and strcpy. 551 * Note that NULL is handled accordingly. 552 */ 553char * 554_mesa_strdup( const char *s ) 555{ 556 if (s) { 557 size_t l = strlen(s); 558 char *s2 = malloc(l + 1); 559 if (s2) 560 strcpy(s2, s); 561 return s2; 562 } 563 else { 564 return NULL; 565 } 566} 567 568/** Wrapper around strtof() */ 569float 570_mesa_strtof( const char *s, char **end ) 571{ 572#if defined(_GNU_SOURCE) && !defined(__CYGWIN__) && !defined(__FreeBSD__) && \ 573 !defined(ANDROID) && !defined(__HAIKU__) && !defined(__UCLIBC__) && \ 574 !defined(__NetBSD__) 575 static locale_t loc = NULL; 576 if (!loc) { 577 loc = newlocale(LC_CTYPE_MASK, "C", NULL); 578 } 579 return strtof_l(s, end, loc); 580#elif defined(_ISOC99_SOURCE) || (defined(_XOPEN_SOURCE) && _XOPEN_SOURCE >= 600) 581 return strtof(s, end); 582#else 583 return (float)strtod(s, end); 584#endif 585} 586 587/** Compute simple checksum/hash for a string */ 588unsigned int 589_mesa_str_checksum(const char *str) 590{ 591 /* This could probably be much better */ 592 unsigned int sum, i; 593 const char *c; 594 sum = i = 1; 595 for (c = str; *c; c++, i++) 596 sum += *c * (i % 100); 597 return sum + i; 598} 599 600 601/*@}*/ 602 603 604/** Needed due to #ifdef's, above. */ 605int 606_mesa_vsnprintf(char *str, size_t size, const char *fmt, va_list args) 607{ 608 return vsnprintf( str, size, fmt, args); 609} 610 611/** Wrapper around vsnprintf() */ 612int 613_mesa_snprintf( char *str, size_t size, const char *fmt, ... ) 614{ 615 int r; 616 va_list args; 617 va_start( args, fmt ); 618 r = vsnprintf( str, size, fmt, args ); 619 va_end( args ); 620 return r; 621} 622 623 624