diff options
Diffstat (limited to 'mesalib/src/mesa/main')
-rw-r--r-- | mesalib/src/mesa/main/imports.c | 2061 | ||||
-rw-r--r-- | mesalib/src/mesa/main/imports.h | 1217 |
2 files changed, 1643 insertions, 1635 deletions
diff --git a/mesalib/src/mesa/main/imports.c b/mesalib/src/mesa/main/imports.c index f98098230..bf89815f2 100644 --- a/mesalib/src/mesa/main/imports.c +++ b/mesalib/src/mesa/main/imports.c @@ -1,1033 +1,1028 @@ -/**
- * \file imports.c
- * Standard C library function wrappers.
- *
- * Imports are services which the device driver or window system or
- * operating system provides to the core renderer. The core renderer (Mesa)
- * will call these functions in order to do memory allocation, simple I/O,
- * etc.
- *
- * Some drivers will want to override/replace this file with something
- * specialized, but that'll be rare.
- *
- * Eventually, I want to move roll the glheader.h file into this.
- *
- * \todo Functions still needed:
- * - scanf
- * - qsort
- * - rand and RAND_MAX
- */
-
-/*
- * Mesa 3-D graphics library
- * Version: 7.1
- *
- * Copyright (C) 1999-2007 Brian Paul All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-
-
-#include "imports.h"
-#include "context.h"
-#include "mtypes.h"
-#include "version.h"
-
-#ifdef _GNU_SOURCE
-#include <locale.h>
-#ifdef __APPLE__
-#include <xlocale.h>
-#endif
-#endif
-
-
-#define MAXSTRING 4000 /* for vsnprintf() */
-
-#ifdef WIN32
-#define vsnprintf _vsnprintf
-#elif defined(__IBMC__) || defined(__IBMCPP__) || ( defined(__VMS) && __CRTL_VER < 70312000 )
-extern int vsnprintf(char *str, size_t count, const char *fmt, va_list arg);
-#ifdef __VMS
-#include "vsnprintf.c"
-#endif
-#endif
-
-/**********************************************************************/
-/** \name Memory */
-/*@{*/
-
-/**
- * Allocate aligned memory.
- *
- * \param bytes number of bytes to allocate.
- * \param alignment alignment (must be greater than zero).
- *
- * Allocates extra memory to accommodate rounding up the address for
- * alignment and to record the real malloc address.
- *
- * \sa _mesa_align_free().
- */
-void *
-_mesa_align_malloc(size_t bytes, unsigned long alignment)
-{
-#if defined(HAVE_POSIX_MEMALIGN)
- void *mem;
- int err = posix_memalign(& mem, alignment, bytes);
- if (err)
- return NULL;
- return mem;
-#elif defined(_WIN32) && defined(_MSC_VER)
- return _aligned_malloc(bytes, alignment);
-#else
- uintptr_t ptr, buf;
-
- ASSERT( alignment > 0 );
-
- ptr = (uintptr_t) malloc(bytes + alignment + sizeof(void *));
- if (!ptr)
- return NULL;
-
- buf = (ptr + alignment + sizeof(void *)) & ~(uintptr_t)(alignment - 1);
- *(uintptr_t *)(buf - sizeof(void *)) = ptr;
-
-#ifdef DEBUG
- /* mark the non-aligned area */
- while ( ptr < buf - sizeof(void *) ) {
- *(unsigned long *)ptr = 0xcdcdcdcd;
- ptr += sizeof(unsigned long);
- }
-#endif
-
- return (void *) buf;
-#endif /* defined(HAVE_POSIX_MEMALIGN) */
-}
-
-/**
- * Same as _mesa_align_malloc(), but using calloc(1, ) instead of
- * malloc()
- */
-void *
-_mesa_align_calloc(size_t bytes, unsigned long alignment)
-{
-#if defined(HAVE_POSIX_MEMALIGN)
- void *mem;
-
- mem = _mesa_align_malloc(bytes, alignment);
- if (mem != NULL) {
- (void) memset(mem, 0, bytes);
- }
-
- return mem;
-#elif defined(_WIN32) && defined(_MSC_VER)
- void *mem;
-
- mem = _aligned_malloc(bytes, alignment);
- if (mem != NULL) {
- (void) memset(mem, 0, bytes);
- }
-
- return mem;
-#else
- uintptr_t ptr, buf;
-
- ASSERT( alignment > 0 );
-
- ptr = (uintptr_t) calloc(1, bytes + alignment + sizeof(void *));
- if (!ptr)
- return NULL;
-
- buf = (ptr + alignment + sizeof(void *)) & ~(uintptr_t)(alignment - 1);
- *(uintptr_t *)(buf - sizeof(void *)) = ptr;
-
-#ifdef DEBUG
- /* mark the non-aligned area */
- while ( ptr < buf - sizeof(void *) ) {
- *(unsigned long *)ptr = 0xcdcdcdcd;
- ptr += sizeof(unsigned long);
- }
-#endif
-
- return (void *)buf;
-#endif /* defined(HAVE_POSIX_MEMALIGN) */
-}
-
-/**
- * Free memory which was allocated with either _mesa_align_malloc()
- * or _mesa_align_calloc().
- * \param ptr pointer to the memory to be freed.
- * The actual address to free is stored in the word immediately before the
- * address the client sees.
- */
-void
-_mesa_align_free(void *ptr)
-{
-#if defined(HAVE_POSIX_MEMALIGN)
- free(ptr);
-#elif defined(_WIN32) && defined(_MSC_VER)
- _aligned_free(ptr);
-#else
- void **cubbyHole = (void **) ((char *) ptr - sizeof(void *));
- void *realAddr = *cubbyHole;
- free(realAddr);
-#endif /* defined(HAVE_POSIX_MEMALIGN) */
-}
-
-/**
- * Reallocate memory, with alignment.
- */
-void *
-_mesa_align_realloc(void *oldBuffer, size_t oldSize, size_t newSize,
- unsigned long alignment)
-{
-#if defined(_WIN32) && defined(_MSC_VER)
- (void) oldSize;
- return _aligned_realloc(oldBuffer, newSize, alignment);
-#else
- const size_t copySize = (oldSize < newSize) ? oldSize : newSize;
- void *newBuf = _mesa_align_malloc(newSize, alignment);
- if (newBuf && oldBuffer && copySize > 0) {
- memcpy(newBuf, oldBuffer, copySize);
- }
- if (oldBuffer)
- _mesa_align_free(oldBuffer);
- return newBuf;
-#endif
-}
-
-
-
-/** Reallocate memory */
-void *
-_mesa_realloc(void *oldBuffer, size_t oldSize, size_t newSize)
-{
- const size_t copySize = (oldSize < newSize) ? oldSize : newSize;
- void *newBuffer = malloc(newSize);
- if (newBuffer && oldBuffer && copySize > 0)
- memcpy(newBuffer, oldBuffer, copySize);
- if (oldBuffer)
- free(oldBuffer);
- return newBuffer;
-}
-
-/**
- * Fill memory with a constant 16bit word.
- * \param dst destination pointer.
- * \param val value.
- * \param n number of words.
- */
-void
-_mesa_memset16( unsigned short *dst, unsigned short val, size_t n )
-{
- while (n-- > 0)
- *dst++ = val;
-}
-
-/*@}*/
-
-
-/**********************************************************************/
-/** \name Math */
-/*@{*/
-
-/** Wrapper around sqrt() */
-double
-_mesa_sqrtd(double x)
-{
- return sqrt(x);
-}
-
-
-/*
- * A High Speed, Low Precision Square Root
- * by Paul Lalonde and Robert Dawson
- * from "Graphics Gems", Academic Press, 1990
- *
- * SPARC implementation of a fast square root by table
- * lookup.
- * SPARC floating point format is as follows:
- *
- * BIT 31 30 23 22 0
- * sign exponent mantissa
- */
-static short sqrttab[0x100]; /* declare table of square roots */
-
-void
-_mesa_init_sqrt_table(void)
-{
-#if defined(USE_IEEE) && !defined(DEBUG)
- unsigned short i;
- fi_type fi; /* to access the bits of a float in C quickly */
- /* we use a union defined in glheader.h */
-
- for(i=0; i<= 0x7f; i++) {
- fi.i = 0;
-
- /*
- * Build a float with the bit pattern i as mantissa
- * and an exponent of 0, stored as 127
- */
-
- fi.i = (i << 16) | (127 << 23);
- fi.f = _mesa_sqrtd(fi.f);
-
- /*
- * Take the square root then strip the first 7 bits of
- * the mantissa into the table
- */
-
- sqrttab[i] = (fi.i & 0x7fffff) >> 16;
-
- /*
- * Repeat the process, this time with an exponent of
- * 1, stored as 128
- */
-
- fi.i = 0;
- fi.i = (i << 16) | (128 << 23);
- fi.f = sqrt(fi.f);
- sqrttab[i+0x80] = (fi.i & 0x7fffff) >> 16;
- }
-#else
- (void) sqrttab; /* silence compiler warnings */
-#endif /*HAVE_FAST_MATH*/
-}
-
-
-/**
- * Single precision square root.
- */
-float
-_mesa_sqrtf( float x )
-{
-#if defined(USE_IEEE) && !defined(DEBUG)
- fi_type num;
- /* to access the bits of a float in C
- * we use a union from glheader.h */
-
- short e; /* the exponent */
- if (x == 0.0F) return 0.0F; /* check for square root of 0 */
- num.f = x;
- e = (num.i >> 23) - 127; /* get the exponent - on a SPARC the */
- /* exponent is stored with 127 added */
- num.i &= 0x7fffff; /* leave only the mantissa */
- if (e & 0x01) num.i |= 0x800000;
- /* the exponent is odd so we have to */
- /* look it up in the second half of */
- /* the lookup table, so we set the */
- /* high bit */
- e >>= 1; /* divide the exponent by two */
- /* note that in C the shift */
- /* operators are sign preserving */
- /* for signed operands */
- /* Do the table lookup, based on the quaternary mantissa,
- * then reconstruct the result back into a float
- */
- num.i = ((sqrttab[num.i >> 16]) << 16) | ((e + 127) << 23);
-
- return num.f;
-#else
- return (float) _mesa_sqrtd((double) x);
-#endif
-}
-
-
-/**
- inv_sqrt - A single precision 1/sqrt routine for IEEE format floats.
- written by Josh Vanderhoof, based on newsgroup posts by James Van Buskirk
- and Vesa Karvonen.
-*/
-float
-_mesa_inv_sqrtf(float n)
-{
-#if defined(USE_IEEE) && !defined(DEBUG)
- float r0, x0, y0;
- float r1, x1, y1;
- float r2, x2, y2;
-#if 0 /* not used, see below -BP */
- float r3, x3, y3;
-#endif
- fi_type u;
- unsigned int magic;
-
- /*
- Exponent part of the magic number -
-
- We want to:
- 1. subtract the bias from the exponent,
- 2. negate it
- 3. divide by two (rounding towards -inf)
- 4. add the bias back
-
- Which is the same as subtracting the exponent from 381 and dividing
- by 2.
-
- floor(-(x - 127) / 2) + 127 = floor((381 - x) / 2)
- */
-
- magic = 381 << 23;
-
- /*
- Significand part of magic number -
-
- With the current magic number, "(magic - u.i) >> 1" will give you:
-
- for 1 <= u.f <= 2: 1.25 - u.f / 4
- for 2 <= u.f <= 4: 1.00 - u.f / 8
-
- This isn't a bad approximation of 1/sqrt. The maximum difference from
- 1/sqrt will be around .06. After three Newton-Raphson iterations, the
- maximum difference is less than 4.5e-8. (Which is actually close
- enough to make the following bias academic...)
-
- To get a better approximation you can add a bias to the magic
- number. For example, if you subtract 1/2 of the maximum difference in
- the first approximation (.03), you will get the following function:
-
- for 1 <= u.f <= 2: 1.22 - u.f / 4
- for 2 <= u.f <= 3.76: 0.97 - u.f / 8
- for 3.76 <= u.f <= 4: 0.72 - u.f / 16
- (The 3.76 to 4 range is where the result is < .5.)
-
- This is the closest possible initial approximation, but with a maximum
- error of 8e-11 after three NR iterations, it is still not perfect. If
- you subtract 0.0332281 instead of .03, the maximum error will be
- 2.5e-11 after three NR iterations, which should be about as close as
- is possible.
-
- for 1 <= u.f <= 2: 1.2167719 - u.f / 4
- for 2 <= u.f <= 3.73: 0.9667719 - u.f / 8
- for 3.73 <= u.f <= 4: 0.7167719 - u.f / 16
-
- */
-
- magic -= (int)(0.0332281 * (1 << 25));
-
- u.f = n;
- u.i = (magic - u.i) >> 1;
-
- /*
- Instead of Newton-Raphson, we use Goldschmidt's algorithm, which
- allows more parallelism. From what I understand, the parallelism
- comes at the cost of less precision, because it lets error
- accumulate across iterations.
- */
- x0 = 1.0f;
- y0 = 0.5f * n;
- r0 = u.f;
-
- x1 = x0 * r0;
- y1 = y0 * r0 * r0;
- r1 = 1.5f - y1;
-
- x2 = x1 * r1;
- y2 = y1 * r1 * r1;
- r2 = 1.5f - y2;
-
-#if 1
- return x2 * r2; /* we can stop here, and be conformant -BP */
-#else
- x3 = x2 * r2;
- y3 = y2 * r2 * r2;
- r3 = 1.5f - y3;
-
- return x3 * r3;
-#endif
-#else
- return (float) (1.0 / sqrt(n));
-#endif
-}
-
-/**
- * Find the first bit set in a word.
- */
-int
-_mesa_ffs(int32_t i)
-{
-#if (defined(_WIN32) ) || defined(__IBMC__) || defined(__IBMCPP__)
- register int bit = 0;
- if (i != 0) {
- if ((i & 0xffff) == 0) {
- bit += 16;
- i >>= 16;
- }
- if ((i & 0xff) == 0) {
- bit += 8;
- i >>= 8;
- }
- if ((i & 0xf) == 0) {
- bit += 4;
- i >>= 4;
- }
- while ((i & 1) == 0) {
- bit++;
- i >>= 1;
- }
- bit++;
- }
- return bit;
-#else
- return ffs(i);
-#endif
-}
-
-
-/**
- * Find position of first bit set in given value.
- * XXX Warning: this function can only be used on 64-bit systems!
- * \return position of least-significant bit set, starting at 1, return zero
- * if no bits set.
- */
-int
-_mesa_ffsll(int64_t val)
-{
-#ifdef ffsll
- return ffsll(val);
-#else
- int bit;
-
- assert(sizeof(val) == 8);
-
- bit = _mesa_ffs((int32_t)val);
- if (bit != 0)
- return bit;
-
- bit = _mesa_ffs((int32_t)(val >> 32));
- if (bit != 0)
- return 32 + bit;
-
- return 0;
-#endif
-}
-
-
-/**
- * Return number of bits set in given GLuint.
- */
-unsigned int
-_mesa_bitcount(unsigned int n)
-{
-#if defined(__GNUC__) && \
- ((_GNUC__ == 3 && __GNUC_MINOR__ >= 4) || __GNUC__ >= 4)
- return __builtin_popcount(n);
-#else
- unsigned int bits;
- for (bits = 0; n > 0; n = n >> 1) {
- bits += (n & 1);
- }
- return bits;
-#endif
-}
-
-
-/**
- * Convert a 4-byte float to a 2-byte half float.
- * Based on code from:
- * http://www.opengl.org/discussion_boards/ubb/Forum3/HTML/008786.html
- */
-GLhalfARB
-_mesa_float_to_half(float val)
-{
- const fi_type fi = {val};
- const int flt_m = fi.i & 0x7fffff;
- const int flt_e = (fi.i >> 23) & 0xff;
- const int flt_s = (fi.i >> 31) & 0x1;
- int s, e, m = 0;
- GLhalfARB result;
-
- /* sign bit */
- s = flt_s;
-
- /* handle special cases */
- if ((flt_e == 0) && (flt_m == 0)) {
- /* zero */
- /* m = 0; - already set */
- e = 0;
- }
- else if ((flt_e == 0) && (flt_m != 0)) {
- /* denorm -- denorm float maps to 0 half */
- /* m = 0; - already set */
- e = 0;
- }
- else if ((flt_e == 0xff) && (flt_m == 0)) {
- /* infinity */
- /* m = 0; - already set */
- e = 31;
- }
- else if ((flt_e == 0xff) && (flt_m != 0)) {
- /* NaN */
- m = 1;
- e = 31;
- }
- else {
- /* regular number */
- const int new_exp = flt_e - 127;
- if (new_exp < -24) {
- /* this maps to 0 */
- /* m = 0; - already set */
- e = 0;
- }
- else if (new_exp < -14) {
- /* this maps to a denorm */
- unsigned int exp_val = (unsigned int) (-14 - new_exp); /* 2^-exp_val*/
- e = 0;
- switch (exp_val) {
- case 0:
- _mesa_warning(NULL,
- "float_to_half: logical error in denorm creation!\n");
- /* m = 0; - already set */
- break;
- case 1: m = 512 + (flt_m >> 14); break;
- case 2: m = 256 + (flt_m >> 15); break;
- case 3: m = 128 + (flt_m >> 16); break;
- case 4: m = 64 + (flt_m >> 17); break;
- case 5: m = 32 + (flt_m >> 18); break;
- case 6: m = 16 + (flt_m >> 19); break;
- case 7: m = 8 + (flt_m >> 20); break;
- case 8: m = 4 + (flt_m >> 21); break;
- case 9: m = 2 + (flt_m >> 22); break;
- case 10: m = 1; break;
- }
- }
- else if (new_exp > 15) {
- /* map this value to infinity */
- /* m = 0; - already set */
- e = 31;
- }
- else {
- /* regular */
- e = new_exp + 15;
- m = flt_m >> 13;
- }
- }
-
- result = (s << 15) | (e << 10) | m;
- return result;
-}
-
-
-/**
- * Convert a 2-byte half float to a 4-byte float.
- * Based on code from:
- * http://www.opengl.org/discussion_boards/ubb/Forum3/HTML/008786.html
- */
-float
-_mesa_half_to_float(GLhalfARB val)
-{
- /* XXX could also use a 64K-entry lookup table */
- const int m = val & 0x3ff;
- const int e = (val >> 10) & 0x1f;
- const int s = (val >> 15) & 0x1;
- int flt_m, flt_e, flt_s;
- fi_type fi;
- float result;
-
- /* sign bit */
- flt_s = s;
-
- /* handle special cases */
- if ((e == 0) && (m == 0)) {
- /* zero */
- flt_m = 0;
- flt_e = 0;
- }
- else if ((e == 0) && (m != 0)) {
- /* denorm -- denorm half will fit in non-denorm single */
- const float half_denorm = 1.0f / 16384.0f; /* 2^-14 */
- float mantissa = ((float) (m)) / 1024.0f;
- float sign = s ? -1.0f : 1.0f;
- return sign * mantissa * half_denorm;
- }
- else if ((e == 31) && (m == 0)) {
- /* infinity */
- flt_e = 0xff;
- flt_m = 0;
- }
- else if ((e == 31) && (m != 0)) {
- /* NaN */
- flt_e = 0xff;
- flt_m = 1;
- }
- else {
- /* regular */
- flt_e = e + 112;
- flt_m = m << 13;
- }
-
- fi.i = (flt_s << 31) | (flt_e << 23) | flt_m;
- result = fi.f;
- return result;
-}
-
-/*@}*/
-
-
-/**********************************************************************/
-/** \name Sort & Search */
-/*@{*/
-
-/**
- * Wrapper for bsearch().
- */
-void *
-_mesa_bsearch( const void *key, const void *base, size_t nmemb, size_t size,
- int (*compar)(const void *, const void *) )
-{
-#if defined(_WIN32_WCE)
- void *mid;
- int cmp;
- while (nmemb) {
- nmemb >>= 1;
- mid = (char *)base + nmemb * size;
- cmp = (*compar)(key, mid);
- if (cmp == 0)
- return mid;
- if (cmp > 0) {
- base = (char *)mid + size;
- --nmemb;
- }
- }
- return NULL;
-#else
- return bsearch(key, base, nmemb, size, compar);
-#endif
-}
-
-/*@}*/
-
-
-/**********************************************************************/
-/** \name Environment vars */
-/*@{*/
-
-/**
- * Wrapper for getenv().
- */
-char *
-_mesa_getenv( const char *var )
-{
-#if defined(_XBOX) || defined(_WIN32_WCE)
- return NULL;
-#else
- return getenv(var);
-#endif
-}
-
-/*@}*/
-
-
-/**********************************************************************/
-/** \name String */
-/*@{*/
-
-/**
- * Implemented using malloc() and strcpy.
- * Note that NULL is handled accordingly.
- */
-char *
-_mesa_strdup( const char *s )
-{
- if (s) {
- size_t l = strlen(s);
- char *s2 = (char *) malloc(l + 1);
- if (s2)
- strcpy(s2, s);
- return s2;
- }
- else {
- return NULL;
- }
-}
-
-/** Wrapper around strtof() */
-float
-_mesa_strtof( const char *s, char **end )
-{
-#if defined(_GNU_SOURCE) && !defined(__CYGWIN__) && !defined(__FreeBSD__)
- static locale_t loc = NULL;
- if (!loc) {
- loc = newlocale(LC_CTYPE_MASK, "C", NULL);
- }
- return strtof_l(s, end, loc);
-#elif defined(_ISOC99_SOURCE) || (defined(_XOPEN_SOURCE) && _XOPEN_SOURCE >= 600)
- return strtof(s, end);
-#else
- return (float)strtod(s, end);
-#endif
-}
-
-/** Compute simple checksum/hash for a string */
-unsigned int
-_mesa_str_checksum(const char *str)
-{
- /* This could probably be much better */
- unsigned int sum, i;
- const char *c;
- sum = i = 1;
- for (c = str; *c; c++, i++)
- sum += *c * (i % 100);
- return sum + i;
-}
-
-
-/*@}*/
-
-
-/** Wrapper around vsnprintf() */
-int
-_mesa_snprintf( char *str, size_t size, const char *fmt, ... )
-{
- int r;
- va_list args;
- va_start( args, fmt );
- r = vsnprintf( str, size, fmt, args );
- va_end( args );
- return r;
-}
-
-
-/**********************************************************************/
-/** \name Diagnostics */
-/*@{*/
-
-static void
-output_if_debug(const char *prefixString, const char *outputString,
- GLboolean newline)
-{
- static int debug = -1;
-
- /* Check the MESA_DEBUG environment variable if it hasn't
- * been checked yet. We only have to check it once...
- */
- if (debug == -1) {
- char *env = _mesa_getenv("MESA_DEBUG");
-
- /* In a debug build, we print warning messages *unless*
- * MESA_DEBUG is 0. In a non-debug build, we don't
- * print warning messages *unless* MESA_DEBUG is
- * set *to any value*.
- */
-#ifdef DEBUG
- debug = (env != NULL && atoi(env) == 0) ? 0 : 1;
-#else
- debug = (env != NULL) ? 1 : 0;
-#endif
- }
-
- /* Now only print the string if we're required to do so. */
- if (debug) {
- fprintf(stderr, "%s: %s", prefixString, outputString);
- if (newline)
- fprintf(stderr, "\n");
-
-#if defined(_WIN32) && !defined(_WIN32_WCE)
- /* stderr from windows applications without console is not usually
- * visible, so communicate with the debugger instead */
- {
- char buf[4096];
- _mesa_snprintf(buf, sizeof(buf), "%s: %s%s", prefixString, outputString, newline ? "\n" : "");
- OutputDebugStringA(buf);
- }
-#endif
- }
-}
-
-
-/**
- * Return string version of GL error code.
- */
-static const char *
-error_string( GLenum error )
-{
- switch (error) {
- case GL_NO_ERROR:
- return "GL_NO_ERROR";
- case GL_INVALID_VALUE:
- return "GL_INVALID_VALUE";
- case GL_INVALID_ENUM:
- return "GL_INVALID_ENUM";
- case GL_INVALID_OPERATION:
- return "GL_INVALID_OPERATION";
- case GL_STACK_OVERFLOW:
- return "GL_STACK_OVERFLOW";
- case GL_STACK_UNDERFLOW:
- return "GL_STACK_UNDERFLOW";
- case GL_OUT_OF_MEMORY:
- return "GL_OUT_OF_MEMORY";
- case GL_TABLE_TOO_LARGE:
- return "GL_TABLE_TOO_LARGE";
- case GL_INVALID_FRAMEBUFFER_OPERATION_EXT:
- return "GL_INVALID_FRAMEBUFFER_OPERATION";
- default:
- return "unknown";
- }
-}
-
-
-/**
- * When a new type of error is recorded, print a message describing
- * previous errors which were accumulated.
- */
-static void
-flush_delayed_errors( struct gl_context *ctx )
-{
- char s[MAXSTRING];
-
- if (ctx->ErrorDebugCount) {
- _mesa_snprintf(s, MAXSTRING, "%d similar %s errors",
- ctx->ErrorDebugCount,
- error_string(ctx->ErrorValue));
-
- output_if_debug("Mesa", s, GL_TRUE);
-
- ctx->ErrorDebugCount = 0;
- }
-}
-
-
-/**
- * Report a warning (a recoverable error condition) to stderr if
- * either DEBUG is defined or the MESA_DEBUG env var is set.
- *
- * \param ctx GL context.
- * \param fmtString printf()-like format string.
- */
-void
-_mesa_warning( struct gl_context *ctx, const char *fmtString, ... )
-{
- char str[MAXSTRING];
- va_list args;
- va_start( args, fmtString );
- (void) vsnprintf( str, MAXSTRING, fmtString, args );
- va_end( args );
-
- if (ctx)
- flush_delayed_errors( ctx );
-
- output_if_debug("Mesa warning", str, GL_TRUE);
-}
-
-
-/**
- * Report an internal implementation problem.
- * Prints the message to stderr via fprintf().
- *
- * \param ctx GL context.
- * \param fmtString problem description string.
- */
-void
-_mesa_problem( const struct gl_context *ctx, const char *fmtString, ... )
-{
- va_list args;
- char str[MAXSTRING];
- (void) ctx;
-
- va_start( args, fmtString );
- vsnprintf( str, MAXSTRING, fmtString, args );
- va_end( args );
-
- fprintf(stderr, "Mesa %s implementation error: %s\n", MESA_VERSION_STRING, str);
- fprintf(stderr, "Please report at bugs.freedesktop.org\n");
-}
-
-
-/**
- * Record an OpenGL state error. These usually occur when the user
- * passes invalid parameters to a GL function.
- *
- * If debugging is enabled (either at compile-time via the DEBUG macro, or
- * run-time via the MESA_DEBUG environment variable), report the error with
- * _mesa_debug().
- *
- * \param ctx the GL context.
- * \param error the error value.
- * \param fmtString printf() style format string, followed by optional args
- */
-void
-_mesa_error( struct gl_context *ctx, GLenum error, const char *fmtString, ... )
-{
- static GLint debug = -1;
-
- /* Check debug environment variable only once:
- */
- if (debug == -1) {
- const char *debugEnv = _mesa_getenv("MESA_DEBUG");
-
-#ifdef DEBUG
- if (debugEnv && strstr(debugEnv, "silent"))
- debug = GL_FALSE;
- else
- debug = GL_TRUE;
-#else
- if (debugEnv)
- debug = GL_TRUE;
- else
- debug = GL_FALSE;
-#endif
- }
-
- if (debug) {
- if (ctx->ErrorValue == error &&
- ctx->ErrorDebugFmtString == fmtString) {
- ctx->ErrorDebugCount++;
- }
- else {
- char s[MAXSTRING], s2[MAXSTRING];
- va_list args;
-
- flush_delayed_errors( ctx );
-
- va_start(args, fmtString);
- vsnprintf(s, MAXSTRING, fmtString, args);
- va_end(args);
-
- _mesa_snprintf(s2, MAXSTRING, "%s in %s", error_string(error), s);
- output_if_debug("Mesa: User error", s2, GL_TRUE);
-
- ctx->ErrorDebugFmtString = fmtString;
- ctx->ErrorDebugCount = 0;
- }
- }
-
- _mesa_record_error(ctx, error);
-}
-
-
-/**
- * Report debug information. Print error message to stderr via fprintf().
- * No-op if DEBUG mode not enabled.
- *
- * \param ctx GL context.
- * \param fmtString printf()-style format string, followed by optional args.
- */
-void
-_mesa_debug( const struct gl_context *ctx, const char *fmtString, ... )
-{
-#ifdef DEBUG
- char s[MAXSTRING];
- va_list args;
- va_start(args, fmtString);
- vsnprintf(s, MAXSTRING, fmtString, args);
- va_end(args);
- output_if_debug("Mesa", s, GL_FALSE);
-#endif /* DEBUG */
- (void) ctx;
- (void) fmtString;
-}
-
-/*@}*/
+/** + * \file imports.c + * Standard C library function wrappers. + * + * Imports are services which the device driver or window system or + * operating system provides to the core renderer. The core renderer (Mesa) + * will call these functions in order to do memory allocation, simple I/O, + * etc. + * + * Some drivers will want to override/replace this file with something + * specialized, but that'll be rare. + * + * Eventually, I want to move roll the glheader.h file into this. + * + * \todo Functions still needed: + * - scanf + * - qsort + * - rand and RAND_MAX + */ + +/* + * Mesa 3-D graphics library + * Version: 7.1 + * + * Copyright (C) 1999-2007 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + + +#include "imports.h" +#include "context.h" +#include "mtypes.h" +#include "version.h" + +#ifdef _GNU_SOURCE +#include <locale.h> +#ifdef __APPLE__ +#include <xlocale.h> +#endif +#endif + + +#define MAXSTRING 4000 /* for vsnprintf() */ + +#ifdef WIN32 +#define vsnprintf _vsnprintf +#elif defined(__IBMC__) || defined(__IBMCPP__) || ( defined(__VMS) && __CRTL_VER < 70312000 ) +extern int vsnprintf(char *str, size_t count, const char *fmt, va_list arg); +#ifdef __VMS +#include "vsnprintf.c" +#endif +#endif + +/**********************************************************************/ +/** \name Memory */ +/*@{*/ + +/** + * Allocate aligned memory. + * + * \param bytes number of bytes to allocate. + * \param alignment alignment (must be greater than zero). + * + * Allocates extra memory to accommodate rounding up the address for + * alignment and to record the real malloc address. + * + * \sa _mesa_align_free(). + */ +void * +_mesa_align_malloc(size_t bytes, unsigned long alignment) +{ +#if defined(HAVE_POSIX_MEMALIGN) + void *mem; + int err = posix_memalign(& mem, alignment, bytes); + if (err) + return NULL; + return mem; +#elif defined(_WIN32) && defined(_MSC_VER) + return _aligned_malloc(bytes, alignment); +#else + uintptr_t ptr, buf; + + ASSERT( alignment > 0 ); + + ptr = (uintptr_t) malloc(bytes + alignment + sizeof(void *)); + if (!ptr) + return NULL; + + buf = (ptr + alignment + sizeof(void *)) & ~(uintptr_t)(alignment - 1); + *(uintptr_t *)(buf - sizeof(void *)) = ptr; + +#ifdef DEBUG + /* mark the non-aligned area */ + while ( ptr < buf - sizeof(void *) ) { + *(unsigned long *)ptr = 0xcdcdcdcd; + ptr += sizeof(unsigned long); + } +#endif + + return (void *) buf; +#endif /* defined(HAVE_POSIX_MEMALIGN) */ +} + +/** + * Same as _mesa_align_malloc(), but using calloc(1, ) instead of + * malloc() + */ +void * +_mesa_align_calloc(size_t bytes, unsigned long alignment) +{ +#if defined(HAVE_POSIX_MEMALIGN) + void *mem; + + mem = _mesa_align_malloc(bytes, alignment); + if (mem != NULL) { + (void) memset(mem, 0, bytes); + } + + return mem; +#elif defined(_WIN32) && defined(_MSC_VER) + void *mem; + + mem = _aligned_malloc(bytes, alignment); + if (mem != NULL) { + (void) memset(mem, 0, bytes); + } + + return mem; +#else + uintptr_t ptr, buf; + + ASSERT( alignment > 0 ); + + ptr = (uintptr_t) calloc(1, bytes + alignment + sizeof(void *)); + if (!ptr) + return NULL; + + buf = (ptr + alignment + sizeof(void *)) & ~(uintptr_t)(alignment - 1); + *(uintptr_t *)(buf - sizeof(void *)) = ptr; + +#ifdef DEBUG + /* mark the non-aligned area */ + while ( ptr < buf - sizeof(void *) ) { + *(unsigned long *)ptr = 0xcdcdcdcd; + ptr += sizeof(unsigned long); + } +#endif + + return (void *)buf; +#endif /* defined(HAVE_POSIX_MEMALIGN) */ +} + +/** + * Free memory which was allocated with either _mesa_align_malloc() + * or _mesa_align_calloc(). + * \param ptr pointer to the memory to be freed. + * The actual address to free is stored in the word immediately before the + * address the client sees. + */ +void +_mesa_align_free(void *ptr) +{ +#if defined(HAVE_POSIX_MEMALIGN) + free(ptr); +#elif defined(_WIN32) && defined(_MSC_VER) + _aligned_free(ptr); +#else + void **cubbyHole = (void **) ((char *) ptr - sizeof(void *)); + void *realAddr = *cubbyHole; + free(realAddr); +#endif /* defined(HAVE_POSIX_MEMALIGN) */ +} + +/** + * Reallocate memory, with alignment. + */ +void * +_mesa_align_realloc(void *oldBuffer, size_t oldSize, size_t newSize, + unsigned long alignment) +{ +#if defined(_WIN32) && defined(_MSC_VER) + (void) oldSize; + return _aligned_realloc(oldBuffer, newSize, alignment); +#else + const size_t copySize = (oldSize < newSize) ? oldSize : newSize; + void *newBuf = _mesa_align_malloc(newSize, alignment); + if (newBuf && oldBuffer && copySize > 0) { + memcpy(newBuf, oldBuffer, copySize); + } + if (oldBuffer) + _mesa_align_free(oldBuffer); + return newBuf; +#endif +} + + + +/** Reallocate memory */ +void * +_mesa_realloc(void *oldBuffer, size_t oldSize, size_t newSize) +{ + const size_t copySize = (oldSize < newSize) ? oldSize : newSize; + void *newBuffer = malloc(newSize); + if (newBuffer && oldBuffer && copySize > 0) + memcpy(newBuffer, oldBuffer, copySize); + if (oldBuffer) + free(oldBuffer); + return newBuffer; +} + +/** + * Fill memory with a constant 16bit word. + * \param dst destination pointer. + * \param val value. + * \param n number of words. + */ +void +_mesa_memset16( unsigned short *dst, unsigned short val, size_t n ) +{ + while (n-- > 0) + *dst++ = val; +} + +/*@}*/ + + +/**********************************************************************/ +/** \name Math */ +/*@{*/ + +/** Wrapper around sqrt() */ +double +_mesa_sqrtd(double x) +{ + return sqrt(x); +} + + +/* + * A High Speed, Low Precision Square Root + * by Paul Lalonde and Robert Dawson + * from "Graphics Gems", Academic Press, 1990 + * + * SPARC implementation of a fast square root by table + * lookup. + * SPARC floating point format is as follows: + * + * BIT 31 30 23 22 0 + * sign exponent mantissa + */ +static short sqrttab[0x100]; /* declare table of square roots */ + +void +_mesa_init_sqrt_table(void) +{ +#if defined(USE_IEEE) && !defined(DEBUG) + unsigned short i; + fi_type fi; /* to access the bits of a float in C quickly */ + /* we use a union defined in glheader.h */ + + for(i=0; i<= 0x7f; i++) { + fi.i = 0; + + /* + * Build a float with the bit pattern i as mantissa + * and an exponent of 0, stored as 127 + */ + + fi.i = (i << 16) | (127 << 23); + fi.f = _mesa_sqrtd(fi.f); + + /* + * Take the square root then strip the first 7 bits of + * the mantissa into the table + */ + + sqrttab[i] = (fi.i & 0x7fffff) >> 16; + + /* + * Repeat the process, this time with an exponent of + * 1, stored as 128 + */ + + fi.i = 0; + fi.i = (i << 16) | (128 << 23); + fi.f = sqrt(fi.f); + sqrttab[i+0x80] = (fi.i & 0x7fffff) >> 16; + } +#else + (void) sqrttab; /* silence compiler warnings */ +#endif /*HAVE_FAST_MATH*/ +} + + +/** + * Single precision square root. + */ +float +_mesa_sqrtf( float x ) +{ +#if defined(USE_IEEE) && !defined(DEBUG) + fi_type num; + /* to access the bits of a float in C + * we use a union from glheader.h */ + + short e; /* the exponent */ + if (x == 0.0F) return 0.0F; /* check for square root of 0 */ + num.f = x; + e = (num.i >> 23) - 127; /* get the exponent - on a SPARC the */ + /* exponent is stored with 127 added */ + num.i &= 0x7fffff; /* leave only the mantissa */ + if (e & 0x01) num.i |= 0x800000; + /* the exponent is odd so we have to */ + /* look it up in the second half of */ + /* the lookup table, so we set the */ + /* high bit */ + e >>= 1; /* divide the exponent by two */ + /* note that in C the shift */ + /* operators are sign preserving */ + /* for signed operands */ + /* Do the table lookup, based on the quaternary mantissa, + * then reconstruct the result back into a float + */ + num.i = ((sqrttab[num.i >> 16]) << 16) | ((e + 127) << 23); + + return num.f; +#else + return (float) _mesa_sqrtd((double) x); +#endif +} + + +/** + inv_sqrt - A single precision 1/sqrt routine for IEEE format floats. + written by Josh Vanderhoof, based on newsgroup posts by James Van Buskirk + and Vesa Karvonen. +*/ +float +_mesa_inv_sqrtf(float n) +{ +#if defined(USE_IEEE) && !defined(DEBUG) + float r0, x0, y0; + float r1, x1, y1; + float r2, x2, y2; +#if 0 /* not used, see below -BP */ + float r3, x3, y3; +#endif + fi_type u; + unsigned int magic; + + /* + Exponent part of the magic number - + + We want to: + 1. subtract the bias from the exponent, + 2. negate it + 3. divide by two (rounding towards -inf) + 4. add the bias back + + Which is the same as subtracting the exponent from 381 and dividing + by 2. + + floor(-(x - 127) / 2) + 127 = floor((381 - x) / 2) + */ + + magic = 381 << 23; + + /* + Significand part of magic number - + + With the current magic number, "(magic - u.i) >> 1" will give you: + + for 1 <= u.f <= 2: 1.25 - u.f / 4 + for 2 <= u.f <= 4: 1.00 - u.f / 8 + + This isn't a bad approximation of 1/sqrt. The maximum difference from + 1/sqrt will be around .06. After three Newton-Raphson iterations, the + maximum difference is less than 4.5e-8. (Which is actually close + enough to make the following bias academic...) + + To get a better approximation you can add a bias to the magic + number. For example, if you subtract 1/2 of the maximum difference in + the first approximation (.03), you will get the following function: + + for 1 <= u.f <= 2: 1.22 - u.f / 4 + for 2 <= u.f <= 3.76: 0.97 - u.f / 8 + for 3.76 <= u.f <= 4: 0.72 - u.f / 16 + (The 3.76 to 4 range is where the result is < .5.) + + This is the closest possible initial approximation, but with a maximum + error of 8e-11 after three NR iterations, it is still not perfect. If + you subtract 0.0332281 instead of .03, the maximum error will be + 2.5e-11 after three NR iterations, which should be about as close as + is possible. + + for 1 <= u.f <= 2: 1.2167719 - u.f / 4 + for 2 <= u.f <= 3.73: 0.9667719 - u.f / 8 + for 3.73 <= u.f <= 4: 0.7167719 - u.f / 16 + + */ + + magic -= (int)(0.0332281 * (1 << 25)); + + u.f = n; + u.i = (magic - u.i) >> 1; + + /* + Instead of Newton-Raphson, we use Goldschmidt's algorithm, which + allows more parallelism. From what I understand, the parallelism + comes at the cost of less precision, because it lets error + accumulate across iterations. + */ + x0 = 1.0f; + y0 = 0.5f * n; + r0 = u.f; + + x1 = x0 * r0; + y1 = y0 * r0 * r0; + r1 = 1.5f - y1; + + x2 = x1 * r1; + y2 = y1 * r1 * r1; + r2 = 1.5f - y2; + +#if 1 + return x2 * r2; /* we can stop here, and be conformant -BP */ +#else + x3 = x2 * r2; + y3 = y2 * r2 * r2; + r3 = 1.5f - y3; + + return x3 * r3; +#endif +#else + return (float) (1.0 / sqrt(n)); +#endif +} + +#ifndef __GNUC__ +/** + * Find the first bit set in a word. + */ +int +_mesa_ffs(int32_t i) +{ +#if (defined(_WIN32) ) || defined(__IBMC__) || defined(__IBMCPP__) + register int bit = 0; + if (i != 0) { + if ((i & 0xffff) == 0) { + bit += 16; + i >>= 16; + } + if ((i & 0xff) == 0) { + bit += 8; + i >>= 8; + } + if ((i & 0xf) == 0) { + bit += 4; + i >>= 4; + } + while ((i & 1) == 0) { + bit++; + i >>= 1; + } + bit++; + } + return bit; +#else + return ffs(i); +#endif +} + + +/** + * Find position of first bit set in given value. + * XXX Warning: this function can only be used on 64-bit systems! + * \return position of least-significant bit set, starting at 1, return zero + * if no bits set. + */ +int +_mesa_ffsll(int64_t val) +{ + int bit; + + assert(sizeof(val) == 8); + + bit = _mesa_ffs((int32_t)val); + if (bit != 0) + return bit; + + bit = _mesa_ffs((int32_t)(val >> 32)); + if (bit != 0) + return 32 + bit; + + return 0; +} + + +#if ((_GNUC__ == 3 && __GNUC_MINOR__ < 4) || __GNUC__ < 4) +/** + * Return number of bits set in given GLuint. + */ +unsigned int +_mesa_bitcount(unsigned int n) +{ + unsigned int bits; + for (bits = 0; n > 0; n = n >> 1) { + bits += (n & 1); + } + return bits; +} +#endif +#endif + + +/** + * Convert a 4-byte float to a 2-byte half float. + * Based on code from: + * http://www.opengl.org/discussion_boards/ubb/Forum3/HTML/008786.html + */ +GLhalfARB +_mesa_float_to_half(float val) +{ + const fi_type fi = {val}; + const int flt_m = fi.i & 0x7fffff; + const int flt_e = (fi.i >> 23) & 0xff; + const int flt_s = (fi.i >> 31) & 0x1; + int s, e, m = 0; + GLhalfARB result; + + /* sign bit */ + s = flt_s; + + /* handle special cases */ + if ((flt_e == 0) && (flt_m == 0)) { + /* zero */ + /* m = 0; - already set */ + e = 0; + } + else if ((flt_e == 0) && (flt_m != 0)) { + /* denorm -- denorm float maps to 0 half */ + /* m = 0; - already set */ + e = 0; + } + else if ((flt_e == 0xff) && (flt_m == 0)) { + /* infinity */ + /* m = 0; - already set */ + e = 31; + } + else if ((flt_e == 0xff) && (flt_m != 0)) { + /* NaN */ + m = 1; + e = 31; + } + else { + /* regular number */ + const int new_exp = flt_e - 127; + if (new_exp < -24) { + /* this maps to 0 */ + /* m = 0; - already set */ + e = 0; + } + else if (new_exp < -14) { + /* this maps to a denorm */ + unsigned int exp_val = (unsigned int) (-14 - new_exp); /* 2^-exp_val*/ + e = 0; + switch (exp_val) { + case 0: + _mesa_warning(NULL, + "float_to_half: logical error in denorm creation!\n"); + /* m = 0; - already set */ + break; + case 1: m = 512 + (flt_m >> 14); break; + case 2: m = 256 + (flt_m >> 15); break; + case 3: m = 128 + (flt_m >> 16); break; + case 4: m = 64 + (flt_m >> 17); break; + case 5: m = 32 + (flt_m >> 18); break; + case 6: m = 16 + (flt_m >> 19); break; + case 7: m = 8 + (flt_m >> 20); break; + case 8: m = 4 + (flt_m >> 21); break; + case 9: m = 2 + (flt_m >> 22); break; + case 10: m = 1; break; + } + } + else if (new_exp > 15) { + /* map this value to infinity */ + /* m = 0; - already set */ + e = 31; + } + else { + /* regular */ + e = new_exp + 15; + m = flt_m >> 13; + } + } + + result = (s << 15) | (e << 10) | m; + return result; +} + + +/** + * Convert a 2-byte half float to a 4-byte float. + * Based on code from: + * http://www.opengl.org/discussion_boards/ubb/Forum3/HTML/008786.html + */ +float +_mesa_half_to_float(GLhalfARB val) +{ + /* XXX could also use a 64K-entry lookup table */ + const int m = val & 0x3ff; + const int e = (val >> 10) & 0x1f; + const int s = (val >> 15) & 0x1; + int flt_m, flt_e, flt_s; + fi_type fi; + float result; + + /* sign bit */ + flt_s = s; + + /* handle special cases */ + if ((e == 0) && (m == 0)) { + /* zero */ + flt_m = 0; + flt_e = 0; + } + else if ((e == 0) && (m != 0)) { + /* denorm -- denorm half will fit in non-denorm single */ + const float half_denorm = 1.0f / 16384.0f; /* 2^-14 */ + float mantissa = ((float) (m)) / 1024.0f; + float sign = s ? -1.0f : 1.0f; + return sign * mantissa * half_denorm; + } + else if ((e == 31) && (m == 0)) { + /* infinity */ + flt_e = 0xff; + flt_m = 0; + } + else if ((e == 31) && (m != 0)) { + /* NaN */ + flt_e = 0xff; + flt_m = 1; + } + else { + /* regular */ + flt_e = e + 112; + flt_m = m << 13; + } + + fi.i = (flt_s << 31) | (flt_e << 23) | flt_m; + result = fi.f; + return result; +} + +/*@}*/ + + +/**********************************************************************/ +/** \name Sort & Search */ +/*@{*/ + +/** + * Wrapper for bsearch(). + */ +void * +_mesa_bsearch( const void *key, const void *base, size_t nmemb, size_t size, + int (*compar)(const void *, const void *) ) +{ +#if defined(_WIN32_WCE) + void *mid; + int cmp; + while (nmemb) { + nmemb >>= 1; + mid = (char *)base + nmemb * size; + cmp = (*compar)(key, mid); + if (cmp == 0) + return mid; + if (cmp > 0) { + base = (char *)mid + size; + --nmemb; + } + } + return NULL; +#else + return bsearch(key, base, nmemb, size, compar); +#endif +} + +/*@}*/ + + +/**********************************************************************/ +/** \name Environment vars */ +/*@{*/ + +/** + * Wrapper for getenv(). + */ +char * +_mesa_getenv( const char *var ) +{ +#if defined(_XBOX) || defined(_WIN32_WCE) + return NULL; +#else + return getenv(var); +#endif +} + +/*@}*/ + + +/**********************************************************************/ +/** \name String */ +/*@{*/ + +/** + * Implemented using malloc() and strcpy. + * Note that NULL is handled accordingly. + */ +char * +_mesa_strdup( const char *s ) +{ + if (s) { + size_t l = strlen(s); + char *s2 = (char *) malloc(l + 1); + if (s2) + strcpy(s2, s); + return s2; + } + else { + return NULL; + } +} + +/** Wrapper around strtof() */ +float +_mesa_strtof( const char *s, char **end ) +{ +#if defined(_GNU_SOURCE) && !defined(__CYGWIN__) && !defined(__FreeBSD__) + static locale_t loc = NULL; + if (!loc) { + loc = newlocale(LC_CTYPE_MASK, "C", NULL); + } + return strtof_l(s, end, loc); +#elif defined(_ISOC99_SOURCE) || (defined(_XOPEN_SOURCE) && _XOPEN_SOURCE >= 600) + return strtof(s, end); +#else + return (float)strtod(s, end); +#endif +} + +/** Compute simple checksum/hash for a string */ +unsigned int +_mesa_str_checksum(const char *str) +{ + /* This could probably be much better */ + unsigned int sum, i; + const char *c; + sum = i = 1; + for (c = str; *c; c++, i++) + sum += *c * (i % 100); + return sum + i; +} + + +/*@}*/ + + +/** Wrapper around vsnprintf() */ +int +_mesa_snprintf( char *str, size_t size, const char *fmt, ... ) +{ + int r; + va_list args; + va_start( args, fmt ); + r = vsnprintf( str, size, fmt, args ); + va_end( args ); + return r; +} + + +/**********************************************************************/ +/** \name Diagnostics */ +/*@{*/ + +static void +output_if_debug(const char *prefixString, const char *outputString, + GLboolean newline) +{ + static int debug = -1; + + /* Check the MESA_DEBUG environment variable if it hasn't + * been checked yet. We only have to check it once... + */ + if (debug == -1) { + char *env = _mesa_getenv("MESA_DEBUG"); + + /* In a debug build, we print warning messages *unless* + * MESA_DEBUG is 0. In a non-debug build, we don't + * print warning messages *unless* MESA_DEBUG is + * set *to any value*. + */ +#ifdef DEBUG + debug = (env != NULL && atoi(env) == 0) ? 0 : 1; +#else + debug = (env != NULL) ? 1 : 0; +#endif + } + + /* Now only print the string if we're required to do so. */ + if (debug) { + fprintf(stderr, "%s: %s", prefixString, outputString); + if (newline) + fprintf(stderr, "\n"); + +#if defined(_WIN32) && !defined(_WIN32_WCE) + /* stderr from windows applications without console is not usually + * visible, so communicate with the debugger instead */ + { + char buf[4096]; + _mesa_snprintf(buf, sizeof(buf), "%s: %s%s", prefixString, outputString, newline ? "\n" : ""); + OutputDebugStringA(buf); + } +#endif + } +} + + +/** + * Return string version of GL error code. + */ +static const char * +error_string( GLenum error ) +{ + switch (error) { + case GL_NO_ERROR: + return "GL_NO_ERROR"; + case GL_INVALID_VALUE: + return "GL_INVALID_VALUE"; + case GL_INVALID_ENUM: + return "GL_INVALID_ENUM"; + case GL_INVALID_OPERATION: + return "GL_INVALID_OPERATION"; + case GL_STACK_OVERFLOW: + return "GL_STACK_OVERFLOW"; + case GL_STACK_UNDERFLOW: + return "GL_STACK_UNDERFLOW"; + case GL_OUT_OF_MEMORY: + return "GL_OUT_OF_MEMORY"; + case GL_TABLE_TOO_LARGE: + return "GL_TABLE_TOO_LARGE"; + case GL_INVALID_FRAMEBUFFER_OPERATION_EXT: + return "GL_INVALID_FRAMEBUFFER_OPERATION"; + default: + return "unknown"; + } +} + + +/** + * When a new type of error is recorded, print a message describing + * previous errors which were accumulated. + */ +static void +flush_delayed_errors( struct gl_context *ctx ) +{ + char s[MAXSTRING]; + + if (ctx->ErrorDebugCount) { + _mesa_snprintf(s, MAXSTRING, "%d similar %s errors", + ctx->ErrorDebugCount, + error_string(ctx->ErrorValue)); + + output_if_debug("Mesa", s, GL_TRUE); + + ctx->ErrorDebugCount = 0; + } +} + + +/** + * Report a warning (a recoverable error condition) to stderr if + * either DEBUG is defined or the MESA_DEBUG env var is set. + * + * \param ctx GL context. + * \param fmtString printf()-like format string. + */ +void +_mesa_warning( struct gl_context *ctx, const char *fmtString, ... ) +{ + char str[MAXSTRING]; + va_list args; + va_start( args, fmtString ); + (void) vsnprintf( str, MAXSTRING, fmtString, args ); + va_end( args ); + + if (ctx) + flush_delayed_errors( ctx ); + + output_if_debug("Mesa warning", str, GL_TRUE); +} + + +/** + * Report an internal implementation problem. + * Prints the message to stderr via fprintf(). + * + * \param ctx GL context. + * \param fmtString problem description string. + */ +void +_mesa_problem( const struct gl_context *ctx, const char *fmtString, ... ) +{ + va_list args; + char str[MAXSTRING]; + (void) ctx; + + va_start( args, fmtString ); + vsnprintf( str, MAXSTRING, fmtString, args ); + va_end( args ); + + fprintf(stderr, "Mesa %s implementation error: %s\n", MESA_VERSION_STRING, str); + fprintf(stderr, "Please report at bugs.freedesktop.org\n"); +} + + +/** + * Record an OpenGL state error. These usually occur when the user + * passes invalid parameters to a GL function. + * + * If debugging is enabled (either at compile-time via the DEBUG macro, or + * run-time via the MESA_DEBUG environment variable), report the error with + * _mesa_debug(). + * + * \param ctx the GL context. + * \param error the error value. + * \param fmtString printf() style format string, followed by optional args + */ +void +_mesa_error( struct gl_context *ctx, GLenum error, const char *fmtString, ... ) +{ + static GLint debug = -1; + + /* Check debug environment variable only once: + */ + if (debug == -1) { + const char *debugEnv = _mesa_getenv("MESA_DEBUG"); + +#ifdef DEBUG + if (debugEnv && strstr(debugEnv, "silent")) + debug = GL_FALSE; + else + debug = GL_TRUE; +#else + if (debugEnv) + debug = GL_TRUE; + else + debug = GL_FALSE; +#endif + } + + if (debug) { + if (ctx->ErrorValue == error && + ctx->ErrorDebugFmtString == fmtString) { + ctx->ErrorDebugCount++; + } + else { + char s[MAXSTRING], s2[MAXSTRING]; + va_list args; + + flush_delayed_errors( ctx ); + + va_start(args, fmtString); + vsnprintf(s, MAXSTRING, fmtString, args); + va_end(args); + + _mesa_snprintf(s2, MAXSTRING, "%s in %s", error_string(error), s); + output_if_debug("Mesa: User error", s2, GL_TRUE); + + ctx->ErrorDebugFmtString = fmtString; + ctx->ErrorDebugCount = 0; + } + } + + _mesa_record_error(ctx, error); +} + + +/** + * Report debug information. Print error message to stderr via fprintf(). + * No-op if DEBUG mode not enabled. + * + * \param ctx GL context. + * \param fmtString printf()-style format string, followed by optional args. + */ +void +_mesa_debug( const struct gl_context *ctx, const char *fmtString, ... ) +{ +#ifdef DEBUG + char s[MAXSTRING]; + va_list args; + va_start(args, fmtString); + vsnprintf(s, MAXSTRING, fmtString, args); + va_end(args); + output_if_debug("Mesa", s, GL_FALSE); +#endif /* DEBUG */ + (void) ctx; + (void) fmtString; +} + +/*@}*/ diff --git a/mesalib/src/mesa/main/imports.h b/mesalib/src/mesa/main/imports.h index af7a8cc00..a994dbcae 100644 --- a/mesalib/src/mesa/main/imports.h +++ b/mesalib/src/mesa/main/imports.h @@ -1,602 +1,615 @@ -/*
- * Mesa 3-D graphics library
- * Version: 7.5
- *
- * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-
-/**
- * \file imports.h
- * Standard C library function wrappers.
- *
- * This file provides wrappers for all the standard C library functions
- * like malloc(), free(), printf(), getenv(), etc.
- */
-
-
-#ifndef IMPORTS_H
-#define IMPORTS_H
-
-
-#include "compiler.h"
-#include "glheader.h"
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
-/**********************************************************************/
-/** Memory macros */
-/*@{*/
-
-/** Allocate \p BYTES bytes */
-#define MALLOC(BYTES) malloc(BYTES)
-/** Allocate and zero \p BYTES bytes */
-#define CALLOC(BYTES) calloc(1, BYTES)
-/** Allocate a structure of type \p T */
-#define MALLOC_STRUCT(T) (struct T *) malloc(sizeof(struct T))
-/** Allocate and zero a structure of type \p T */
-#define CALLOC_STRUCT(T) (struct T *) calloc(1, sizeof(struct T))
-/** Free memory */
-#define FREE(PTR) free(PTR)
-
-/*@}*/
-
-
-/*
- * For GL_ARB_vertex_buffer_object we need to treat vertex array pointers
- * as offsets into buffer stores. Since the vertex array pointer and
- * buffer store pointer are both pointers and we need to add them, we use
- * this macro.
- * Both pointers/offsets are expressed in bytes.
- */
-#define ADD_POINTERS(A, B) ( (GLubyte *) (A) + (uintptr_t) (B) )
-
-
-/**
- * Sometimes we treat GLfloats as GLints. On x86 systems, moving a float
- * as a int (thereby using integer registers instead of FP registers) is
- * a performance win. Typically, this can be done with ordinary casts.
- * But with gcc's -fstrict-aliasing flag (which defaults to on in gcc 3.0)
- * these casts generate warnings.
- * The following union typedef is used to solve that.
- */
-typedef union { GLfloat f; GLint i; } fi_type;
-
-
-
-/**********************************************************************
- * Math macros
- */
-
-#define MAX_GLUSHORT 0xffff
-#define MAX_GLUINT 0xffffffff
-
-/* Degrees to radians conversion: */
-#define DEG2RAD (M_PI/180.0)
-
-
-/***
- *** SQRTF: single-precision square root
- ***/
-#if 0 /* _mesa_sqrtf() not accurate enough - temporarily disabled */
-# define SQRTF(X) _mesa_sqrtf(X)
-#else
-# define SQRTF(X) (float) sqrt((float) (X))
-#endif
-
-
-/***
- *** INV_SQRTF: single-precision inverse square root
- ***/
-#if 0
-#define INV_SQRTF(X) _mesa_inv_sqrt(X)
-#else
-#define INV_SQRTF(X) (1.0F / SQRTF(X)) /* this is faster on a P4 */
-#endif
-
-
-/**
- * \name Work-arounds for platforms that lack C99 math functions
- */
-/*@{*/
-#if (!defined(_XOPEN_SOURCE) || (_XOPEN_SOURCE < 600)) && !defined(_ISOC99_SOURCE) \
- && (!defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L)) \
- && (!defined(_MSC_VER) || (_MSC_VER < 1400))
-#define acosf(f) ((float) acos(f))
-#define asinf(f) ((float) asin(f))
-#define atan2f(x,y) ((float) atan2(x,y))
-#define atanf(f) ((float) atan(f))
-#define cielf(f) ((float) ciel(f))
-#define cosf(f) ((float) cos(f))
-#define coshf(f) ((float) cosh(f))
-#define expf(f) ((float) exp(f))
-#define exp2f(f) ((float) exp2(f))
-#define floorf(f) ((float) floor(f))
-#define logf(f) ((float) log(f))
-#define log2f(f) ((float) log2(f))
-#define powf(x,y) ((float) pow(x,y))
-#define sinf(f) ((float) sin(f))
-#define sinhf(f) ((float) sinh(f))
-#define sqrtf(f) ((float) sqrt(f))
-#define tanf(f) ((float) tan(f))
-#define tanhf(f) ((float) tanh(f))
-#define acoshf(f) ((float) acosh(f))
-#define asinhf(f) ((float) asinh(f))
-#define atanhf(f) ((float) atanh(f))
-#endif
-
-#if defined(_MSC_VER)
-static INLINE float truncf(float x) { return x < 0.0f ? ceilf(x) : floorf(x); }
-static INLINE float exp2f(float x) { return powf(2.0f, x); }
-static INLINE float log2f(float x) { return logf(x) * 1.442695041f; }
-static INLINE float asinhf(float x) { return logf(x + sqrtf(x * x + 1.0f)); }
-static INLINE float acoshf(float x) { return logf(x + sqrtf(x * x - 1.0f)); }
-static INLINE float atanhf(float x) { return (logf(1.0f + x) - logf(1.0f - x)) / 2.0f; }
-static INLINE int isblank(int ch) { return ch == ' ' || ch == '\t'; }
-#define strtoll(p, e, b) _strtoi64(p, e, b)
-#endif
-/*@}*/
-
-/***
- *** LOG2: Log base 2 of float
- ***/
-#ifdef USE_IEEE
-#if 0
-/* This is pretty fast, but not accurate enough (only 2 fractional bits).
- * Based on code from http://www.stereopsis.com/log2.html
- */
-static INLINE GLfloat LOG2(GLfloat x)
-{
- const GLfloat y = x * x * x * x;
- const GLuint ix = *((GLuint *) &y);
- const GLuint exp = (ix >> 23) & 0xFF;
- const GLint log2 = ((GLint) exp) - 127;
- return (GLfloat) log2 * (1.0 / 4.0); /* 4, because of x^4 above */
-}
-#endif
-/* Pretty fast, and accurate.
- * Based on code from http://www.flipcode.com/totd/
- */
-static INLINE GLfloat LOG2(GLfloat val)
-{
- fi_type num;
- GLint log_2;
- num.f = val;
- log_2 = ((num.i >> 23) & 255) - 128;
- num.i &= ~(255 << 23);
- num.i += 127 << 23;
- num.f = ((-1.0f/3) * num.f + 2) * num.f - 2.0f/3;
- return num.f + log_2;
-}
-#else
-/*
- * NOTE: log_base_2(x) = log(x) / log(2)
- * NOTE: 1.442695 = 1/log(2).
- */
-#define LOG2(x) ((GLfloat) (log(x) * 1.442695F))
-#endif
-
-
-/***
- *** IS_INF_OR_NAN: test if float is infinite or NaN
- ***/
-#ifdef USE_IEEE
-static INLINE int IS_INF_OR_NAN( float x )
-{
- fi_type tmp;
- tmp.f = x;
- return !(int)((unsigned int)((tmp.i & 0x7fffffff)-0x7f800000) >> 31);
-}
-#elif defined(isfinite)
-#define IS_INF_OR_NAN(x) (!isfinite(x))
-#elif defined(finite)
-#define IS_INF_OR_NAN(x) (!finite(x))
-#elif defined(__VMS)
-#define IS_INF_OR_NAN(x) (!finite(x))
-#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
-#define IS_INF_OR_NAN(x) (!isfinite(x))
-#else
-#define IS_INF_OR_NAN(x) (!finite(x))
-#endif
-
-
-/***
- *** IS_NEGATIVE: test if float is negative
- ***/
-#if defined(USE_IEEE)
-static INLINE int GET_FLOAT_BITS( float x )
-{
- fi_type fi;
- fi.f = x;
- return fi.i;
-}
-#define IS_NEGATIVE(x) (GET_FLOAT_BITS(x) < 0)
-#else
-#define IS_NEGATIVE(x) (x < 0.0F)
-#endif
-
-
-/***
- *** DIFFERENT_SIGNS: test if two floats have opposite signs
- ***/
-#if defined(USE_IEEE)
-#define DIFFERENT_SIGNS(x,y) ((GET_FLOAT_BITS(x) ^ GET_FLOAT_BITS(y)) & (1<<31))
-#else
-/* Could just use (x*y<0) except for the flatshading requirements.
- * Maybe there's a better way?
- */
-#define DIFFERENT_SIGNS(x,y) ((x) * (y) <= 0.0F && (x) - (y) != 0.0F)
-#endif
-
-
-/***
- *** CEILF: ceiling of float
- *** FLOORF: floor of float
- *** FABSF: absolute value of float
- *** LOGF: the natural logarithm (base e) of the value
- *** EXPF: raise e to the value
- *** LDEXPF: multiply value by an integral power of two
- *** FREXPF: extract mantissa and exponent from value
- ***/
-#if defined(__gnu_linux__)
-/* C99 functions */
-#define CEILF(x) ceilf(x)
-#define FLOORF(x) floorf(x)
-#define FABSF(x) fabsf(x)
-#define LOGF(x) logf(x)
-#define EXPF(x) expf(x)
-#define LDEXPF(x,y) ldexpf(x,y)
-#define FREXPF(x,y) frexpf(x,y)
-#else
-#define CEILF(x) ((GLfloat) ceil(x))
-#define FLOORF(x) ((GLfloat) floor(x))
-#define FABSF(x) ((GLfloat) fabs(x))
-#define LOGF(x) ((GLfloat) log(x))
-#define EXPF(x) ((GLfloat) exp(x))
-#define LDEXPF(x,y) ((GLfloat) ldexp(x,y))
-#define FREXPF(x,y) ((GLfloat) frexp(x,y))
-#endif
-
-
-/***
- *** IROUND: return (as an integer) float rounded to nearest integer
- ***/
-#if defined(USE_X86_ASM) && defined(__GNUC__) && defined(__i386__)
-static INLINE int iround(float f)
-{
- int r;
- __asm__ ("fistpl %0" : "=m" (r) : "t" (f) : "st");
- return r;
-}
-#define IROUND(x) iround(x)
-#elif defined(USE_X86_ASM) && defined(_MSC_VER)
-static INLINE int iround(float f)
-{
- int r;
- _asm {
- fld f
- fistp r
- }
- return r;
-}
-#define IROUND(x) iround(x)
-#elif defined(__WATCOMC__) && defined(__386__)
-long iround(float f);
-#pragma aux iround = \
- "push eax" \
- "fistp dword ptr [esp]" \
- "pop eax" \
- parm [8087] \
- value [eax] \
- modify exact [eax];
-#define IROUND(x) iround(x)
-#else
-#define IROUND(f) ((int) (((f) >= 0.0F) ? ((f) + 0.5F) : ((f) - 0.5F)))
-#endif
-
-#define IROUND64(f) ((GLint64) (((f) >= 0.0F) ? ((f) + 0.5F) : ((f) - 0.5F)))
-
-/***
- *** IROUND_POS: return (as an integer) positive float rounded to nearest int
- ***/
-#ifdef DEBUG
-#define IROUND_POS(f) (assert((f) >= 0.0F), IROUND(f))
-#else
-#define IROUND_POS(f) (IROUND(f))
-#endif
-
-
-/***
- *** IFLOOR: return (as an integer) floor of float
- ***/
-#if defined(USE_X86_ASM) && defined(__GNUC__) && defined(__i386__)
-/*
- * IEEE floor for computers that round to nearest or even.
- * 'f' must be between -4194304 and 4194303.
- * This floor operation is done by "(iround(f + .5) + iround(f - .5)) >> 1",
- * but uses some IEEE specific tricks for better speed.
- * Contributed by Josh Vanderhoof
- */
-static INLINE int ifloor(float f)
-{
- int ai, bi;
- double af, bf;
- af = (3 << 22) + 0.5 + (double)f;
- bf = (3 << 22) + 0.5 - (double)f;
- /* GCC generates an extra fstp/fld without this. */
- __asm__ ("fstps %0" : "=m" (ai) : "t" (af) : "st");
- __asm__ ("fstps %0" : "=m" (bi) : "t" (bf) : "st");
- return (ai - bi) >> 1;
-}
-#define IFLOOR(x) ifloor(x)
-#elif defined(USE_IEEE)
-static INLINE int ifloor(float f)
-{
- int ai, bi;
- double af, bf;
- fi_type u;
-
- af = (3 << 22) + 0.5 + (double)f;
- bf = (3 << 22) + 0.5 - (double)f;
- u.f = (float) af; ai = u.i;
- u.f = (float) bf; bi = u.i;
- return (ai - bi) >> 1;
-}
-#define IFLOOR(x) ifloor(x)
-#else
-static INLINE int ifloor(float f)
-{
- int i = IROUND(f);
- return (i > f) ? i - 1 : i;
-}
-#define IFLOOR(x) ifloor(x)
-#endif
-
-
-/***
- *** ICEIL: return (as an integer) ceiling of float
- ***/
-#if defined(USE_X86_ASM) && defined(__GNUC__) && defined(__i386__)
-/*
- * IEEE ceil for computers that round to nearest or even.
- * 'f' must be between -4194304 and 4194303.
- * This ceil operation is done by "(iround(f + .5) + iround(f - .5) + 1) >> 1",
- * but uses some IEEE specific tricks for better speed.
- * Contributed by Josh Vanderhoof
- */
-static INLINE int iceil(float f)
-{
- int ai, bi;
- double af, bf;
- af = (3 << 22) + 0.5 + (double)f;
- bf = (3 << 22) + 0.5 - (double)f;
- /* GCC generates an extra fstp/fld without this. */
- __asm__ ("fstps %0" : "=m" (ai) : "t" (af) : "st");
- __asm__ ("fstps %0" : "=m" (bi) : "t" (bf) : "st");
- return (ai - bi + 1) >> 1;
-}
-#define ICEIL(x) iceil(x)
-#elif defined(USE_IEEE)
-static INLINE int iceil(float f)
-{
- int ai, bi;
- double af, bf;
- fi_type u;
- af = (3 << 22) + 0.5 + (double)f;
- bf = (3 << 22) + 0.5 - (double)f;
- u.f = (float) af; ai = u.i;
- u.f = (float) bf; bi = u.i;
- return (ai - bi + 1) >> 1;
-}
-#define ICEIL(x) iceil(x)
-#else
-static INLINE int iceil(float f)
-{
- int i = IROUND(f);
- return (i < f) ? i + 1 : i;
-}
-#define ICEIL(x) iceil(x)
-#endif
-
-
-/**
- * Is x a power of two?
- */
-static INLINE int
-_mesa_is_pow_two(int x)
-{
- return !(x & (x - 1));
-}
-
-/**
- * Round given integer to next higer power of two
- * If X is zero result is undefined.
- *
- * Source for the fallback implementation is
- * Sean Eron Anderson's webpage "Bit Twiddling Hacks"
- * http://graphics.stanford.edu/~seander/bithacks.html
- *
- * When using builtin function have to do some work
- * for case when passed values 1 to prevent hiting
- * undefined result from __builtin_clz. Undefined
- * results would be different depending on optimization
- * level used for build.
- */
-static INLINE int32_t
-_mesa_next_pow_two_32(uint32_t x)
-{
-#if defined(__GNUC__) && \
- ((__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || __GNUC__ >= 4)
- uint32_t y = (x != 1);
- return (1 + y) << ((__builtin_clz(x - y) ^ 31) );
-#else
- x--;
- x |= x >> 1;
- x |= x >> 2;
- x |= x >> 4;
- x |= x >> 8;
- x |= x >> 16;
- x++;
- return x;
-#endif
-}
-
-static INLINE int64_t
-_mesa_next_pow_two_64(uint64_t x)
-{
-#if defined(__GNUC__) && \
- ((__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || __GNUC__ >= 4)
- uint64_t y = (x != 1);
- if (sizeof(x) == sizeof(long))
- return (1 + y) << ((__builtin_clzl(x - y) ^ 63));
- else
- return (1 + y) << ((__builtin_clzll(x - y) ^ 63));
-#else
- x--;
- x |= x >> 1;
- x |= x >> 2;
- x |= x >> 4;
- x |= x >> 8;
- x |= x >> 16;
- x |= x >> 32;
- x++;
- return x;
-#endif
-}
-
-
-/**
- * Return 1 if this is a little endian machine, 0 if big endian.
- */
-static INLINE GLboolean
-_mesa_little_endian(void)
-{
- const GLuint ui = 1; /* intentionally not static */
- return *((const GLubyte *) &ui);
-}
-
-
-
-/**********************************************************************
- * Functions
- */
-
-extern void *
-_mesa_align_malloc( size_t bytes, unsigned long alignment );
-
-extern void *
-_mesa_align_calloc( size_t bytes, unsigned long alignment );
-
-extern void
-_mesa_align_free( void *ptr );
-
-extern void *
-_mesa_align_realloc(void *oldBuffer, size_t oldSize, size_t newSize,
- unsigned long alignment);
-
-extern void *
-_mesa_exec_malloc( GLuint size );
-
-extern void
-_mesa_exec_free( void *addr );
-
-extern void *
-_mesa_realloc( void *oldBuffer, size_t oldSize, size_t newSize );
-
-extern void
-_mesa_memset16( unsigned short *dst, unsigned short val, size_t n );
-
-extern double
-_mesa_sqrtd(double x);
-
-extern float
-_mesa_sqrtf(float x);
-
-extern float
-_mesa_inv_sqrtf(float x);
-
-extern void
-_mesa_init_sqrt_table(void);
-
-extern int
-_mesa_ffs(int32_t i);
-
-extern int
-_mesa_ffsll(int64_t i);
-
-extern unsigned int
-_mesa_bitcount(unsigned int n);
-
-extern GLhalfARB
-_mesa_float_to_half(float f);
-
-extern float
-_mesa_half_to_float(GLhalfARB h);
-
-
-extern void *
-_mesa_bsearch( const void *key, const void *base, size_t nmemb, size_t size,
- int (*compar)(const void *, const void *) );
-
-extern char *
-_mesa_getenv( const char *var );
-
-extern char *
-_mesa_strdup( const char *s );
-
-extern float
-_mesa_strtof( const char *s, char **end );
-
-extern unsigned int
-_mesa_str_checksum(const char *str);
-
-extern int
-_mesa_snprintf( char *str, size_t size, const char *fmt, ... ) PRINTFLIKE(3, 4);
-
-struct gl_context;
-
-extern void
-_mesa_warning( struct gl_context *gc, const char *fmtString, ... ) PRINTFLIKE(2, 3);
-
-extern void
-_mesa_problem( const struct gl_context *ctx, const char *fmtString, ... ) PRINTFLIKE(2, 3);
-
-extern void
-_mesa_error( struct gl_context *ctx, GLenum error, const char *fmtString, ... ) PRINTFLIKE(3, 4);
-
-extern void
-_mesa_debug( const struct gl_context *ctx, const char *fmtString, ... ) PRINTFLIKE(2, 3);
-
-
-#if defined(_MSC_VER) && !defined(snprintf)
-#define snprintf _snprintf
-#endif
-
-
-#ifdef __cplusplus
-}
-#endif
-
-
-#endif /* IMPORTS_H */
+/* + * Mesa 3-D graphics library + * Version: 7.5 + * + * Copyright (C) 1999-2008 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +/** + * \file imports.h + * Standard C library function wrappers. + * + * This file provides wrappers for all the standard C library functions + * like malloc(), free(), printf(), getenv(), etc. + */ + + +#ifndef IMPORTS_H +#define IMPORTS_H + + +#include "compiler.h" +#include "glheader.h" + + +#ifdef __cplusplus +extern "C" { +#endif + + +/**********************************************************************/ +/** Memory macros */ +/*@{*/ + +/** Allocate \p BYTES bytes */ +#define MALLOC(BYTES) malloc(BYTES) +/** Allocate and zero \p BYTES bytes */ +#define CALLOC(BYTES) calloc(1, BYTES) +/** Allocate a structure of type \p T */ +#define MALLOC_STRUCT(T) (struct T *) malloc(sizeof(struct T)) +/** Allocate and zero a structure of type \p T */ +#define CALLOC_STRUCT(T) (struct T *) calloc(1, sizeof(struct T)) +/** Free memory */ +#define FREE(PTR) free(PTR) + +/*@}*/ + + +/* + * For GL_ARB_vertex_buffer_object we need to treat vertex array pointers + * as offsets into buffer stores. Since the vertex array pointer and + * buffer store pointer are both pointers and we need to add them, we use + * this macro. + * Both pointers/offsets are expressed in bytes. + */ +#define ADD_POINTERS(A, B) ( (GLubyte *) (A) + (uintptr_t) (B) ) + + +/** + * Sometimes we treat GLfloats as GLints. On x86 systems, moving a float + * as a int (thereby using integer registers instead of FP registers) is + * a performance win. Typically, this can be done with ordinary casts. + * But with gcc's -fstrict-aliasing flag (which defaults to on in gcc 3.0) + * these casts generate warnings. + * The following union typedef is used to solve that. + */ +typedef union { GLfloat f; GLint i; } fi_type; + + + +/********************************************************************** + * Math macros + */ + +#define MAX_GLUSHORT 0xffff +#define MAX_GLUINT 0xffffffff + +/* Degrees to radians conversion: */ +#define DEG2RAD (M_PI/180.0) + + +/*** + *** SQRTF: single-precision square root + ***/ +#if 0 /* _mesa_sqrtf() not accurate enough - temporarily disabled */ +# define SQRTF(X) _mesa_sqrtf(X) +#else +# define SQRTF(X) (float) sqrt((float) (X)) +#endif + + +/*** + *** INV_SQRTF: single-precision inverse square root + ***/ +#if 0 +#define INV_SQRTF(X) _mesa_inv_sqrt(X) +#else +#define INV_SQRTF(X) (1.0F / SQRTF(X)) /* this is faster on a P4 */ +#endif + + +/** + * \name Work-arounds for platforms that lack C99 math functions + */ +/*@{*/ +#if (!defined(_XOPEN_SOURCE) || (_XOPEN_SOURCE < 600)) && !defined(_ISOC99_SOURCE) \ + && (!defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L)) \ + && (!defined(_MSC_VER) || (_MSC_VER < 1400)) +#define acosf(f) ((float) acos(f)) +#define asinf(f) ((float) asin(f)) +#define atan2f(x,y) ((float) atan2(x,y)) +#define atanf(f) ((float) atan(f)) +#define cielf(f) ((float) ciel(f)) +#define cosf(f) ((float) cos(f)) +#define coshf(f) ((float) cosh(f)) +#define expf(f) ((float) exp(f)) +#define exp2f(f) ((float) exp2(f)) +#define floorf(f) ((float) floor(f)) +#define logf(f) ((float) log(f)) +#define log2f(f) ((float) log2(f)) +#define powf(x,y) ((float) pow(x,y)) +#define sinf(f) ((float) sin(f)) +#define sinhf(f) ((float) sinh(f)) +#define sqrtf(f) ((float) sqrt(f)) +#define tanf(f) ((float) tan(f)) +#define tanhf(f) ((float) tanh(f)) +#define acoshf(f) ((float) acosh(f)) +#define asinhf(f) ((float) asinh(f)) +#define atanhf(f) ((float) atanh(f)) +#endif + +#if defined(_MSC_VER) +static INLINE float truncf(float x) { return x < 0.0f ? ceilf(x) : floorf(x); } +static INLINE float exp2f(float x) { return powf(2.0f, x); } +static INLINE float log2f(float x) { return logf(x) * 1.442695041f; } +static INLINE float asinhf(float x) { return logf(x + sqrtf(x * x + 1.0f)); } +static INLINE float acoshf(float x) { return logf(x + sqrtf(x * x - 1.0f)); } +static INLINE float atanhf(float x) { return (logf(1.0f + x) - logf(1.0f - x)) / 2.0f; } +static INLINE int isblank(int ch) { return ch == ' ' || ch == '\t'; } +#define strtoll(p, e, b) _strtoi64(p, e, b) +#endif +/*@}*/ + +/*** + *** LOG2: Log base 2 of float + ***/ +#ifdef USE_IEEE +#if 0 +/* This is pretty fast, but not accurate enough (only 2 fractional bits). + * Based on code from http://www.stereopsis.com/log2.html + */ +static INLINE GLfloat LOG2(GLfloat x) +{ + const GLfloat y = x * x * x * x; + const GLuint ix = *((GLuint *) &y); + const GLuint exp = (ix >> 23) & 0xFF; + const GLint log2 = ((GLint) exp) - 127; + return (GLfloat) log2 * (1.0 / 4.0); /* 4, because of x^4 above */ +} +#endif +/* Pretty fast, and accurate. + * Based on code from http://www.flipcode.com/totd/ + */ +static INLINE GLfloat LOG2(GLfloat val) +{ + fi_type num; + GLint log_2; + num.f = val; + log_2 = ((num.i >> 23) & 255) - 128; + num.i &= ~(255 << 23); + num.i += 127 << 23; + num.f = ((-1.0f/3) * num.f + 2) * num.f - 2.0f/3; + return num.f + log_2; +} +#else +/* + * NOTE: log_base_2(x) = log(x) / log(2) + * NOTE: 1.442695 = 1/log(2). + */ +#define LOG2(x) ((GLfloat) (log(x) * 1.442695F)) +#endif + + +/*** + *** IS_INF_OR_NAN: test if float is infinite or NaN + ***/ +#ifdef USE_IEEE +static INLINE int IS_INF_OR_NAN( float x ) +{ + fi_type tmp; + tmp.f = x; + return !(int)((unsigned int)((tmp.i & 0x7fffffff)-0x7f800000) >> 31); +} +#elif defined(isfinite) +#define IS_INF_OR_NAN(x) (!isfinite(x)) +#elif defined(finite) +#define IS_INF_OR_NAN(x) (!finite(x)) +#elif defined(__VMS) +#define IS_INF_OR_NAN(x) (!finite(x)) +#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L +#define IS_INF_OR_NAN(x) (!isfinite(x)) +#else +#define IS_INF_OR_NAN(x) (!finite(x)) +#endif + + +/*** + *** IS_NEGATIVE: test if float is negative + ***/ +#if defined(USE_IEEE) +static INLINE int GET_FLOAT_BITS( float x ) +{ + fi_type fi; + fi.f = x; + return fi.i; +} +#define IS_NEGATIVE(x) (GET_FLOAT_BITS(x) < 0) +#else +#define IS_NEGATIVE(x) (x < 0.0F) +#endif + + +/*** + *** DIFFERENT_SIGNS: test if two floats have opposite signs + ***/ +#if defined(USE_IEEE) +#define DIFFERENT_SIGNS(x,y) ((GET_FLOAT_BITS(x) ^ GET_FLOAT_BITS(y)) & (1<<31)) +#else +/* Could just use (x*y<0) except for the flatshading requirements. + * Maybe there's a better way? + */ +#define DIFFERENT_SIGNS(x,y) ((x) * (y) <= 0.0F && (x) - (y) != 0.0F) +#endif + + +/*** + *** CEILF: ceiling of float + *** FLOORF: floor of float + *** FABSF: absolute value of float + *** LOGF: the natural logarithm (base e) of the value + *** EXPF: raise e to the value + *** LDEXPF: multiply value by an integral power of two + *** FREXPF: extract mantissa and exponent from value + ***/ +#if defined(__gnu_linux__) +/* C99 functions */ +#define CEILF(x) ceilf(x) +#define FLOORF(x) floorf(x) +#define FABSF(x) fabsf(x) +#define LOGF(x) logf(x) +#define EXPF(x) expf(x) +#define LDEXPF(x,y) ldexpf(x,y) +#define FREXPF(x,y) frexpf(x,y) +#else +#define CEILF(x) ((GLfloat) ceil(x)) +#define FLOORF(x) ((GLfloat) floor(x)) +#define FABSF(x) ((GLfloat) fabs(x)) +#define LOGF(x) ((GLfloat) log(x)) +#define EXPF(x) ((GLfloat) exp(x)) +#define LDEXPF(x,y) ((GLfloat) ldexp(x,y)) +#define FREXPF(x,y) ((GLfloat) frexp(x,y)) +#endif + + +/*** + *** IROUND: return (as an integer) float rounded to nearest integer + ***/ +#if defined(USE_X86_ASM) && defined(__GNUC__) && defined(__i386__) +static INLINE int iround(float f) +{ + int r; + __asm__ ("fistpl %0" : "=m" (r) : "t" (f) : "st"); + return r; +} +#define IROUND(x) iround(x) +#elif defined(USE_X86_ASM) && defined(_MSC_VER) +static INLINE int iround(float f) +{ + int r; + _asm { + fld f + fistp r + } + return r; +} +#define IROUND(x) iround(x) +#elif defined(__WATCOMC__) && defined(__386__) +long iround(float f); +#pragma aux iround = \ + "push eax" \ + "fistp dword ptr [esp]" \ + "pop eax" \ + parm [8087] \ + value [eax] \ + modify exact [eax]; +#define IROUND(x) iround(x) +#else +#define IROUND(f) ((int) (((f) >= 0.0F) ? ((f) + 0.5F) : ((f) - 0.5F))) +#endif + +#define IROUND64(f) ((GLint64) (((f) >= 0.0F) ? ((f) + 0.5F) : ((f) - 0.5F))) + +/*** + *** IROUND_POS: return (as an integer) positive float rounded to nearest int + ***/ +#ifdef DEBUG +#define IROUND_POS(f) (assert((f) >= 0.0F), IROUND(f)) +#else +#define IROUND_POS(f) (IROUND(f)) +#endif + + +/*** + *** IFLOOR: return (as an integer) floor of float + ***/ +#if defined(USE_X86_ASM) && defined(__GNUC__) && defined(__i386__) +/* + * IEEE floor for computers that round to nearest or even. + * 'f' must be between -4194304 and 4194303. + * This floor operation is done by "(iround(f + .5) + iround(f - .5)) >> 1", + * but uses some IEEE specific tricks for better speed. + * Contributed by Josh Vanderhoof + */ +static INLINE int ifloor(float f) +{ + int ai, bi; + double af, bf; + af = (3 << 22) + 0.5 + (double)f; + bf = (3 << 22) + 0.5 - (double)f; + /* GCC generates an extra fstp/fld without this. */ + __asm__ ("fstps %0" : "=m" (ai) : "t" (af) : "st"); + __asm__ ("fstps %0" : "=m" (bi) : "t" (bf) : "st"); + return (ai - bi) >> 1; +} +#define IFLOOR(x) ifloor(x) +#elif defined(USE_IEEE) +static INLINE int ifloor(float f) +{ + int ai, bi; + double af, bf; + fi_type u; + + af = (3 << 22) + 0.5 + (double)f; + bf = (3 << 22) + 0.5 - (double)f; + u.f = (float) af; ai = u.i; + u.f = (float) bf; bi = u.i; + return (ai - bi) >> 1; +} +#define IFLOOR(x) ifloor(x) +#else +static INLINE int ifloor(float f) +{ + int i = IROUND(f); + return (i > f) ? i - 1 : i; +} +#define IFLOOR(x) ifloor(x) +#endif + + +/*** + *** ICEIL: return (as an integer) ceiling of float + ***/ +#if defined(USE_X86_ASM) && defined(__GNUC__) && defined(__i386__) +/* + * IEEE ceil for computers that round to nearest or even. + * 'f' must be between -4194304 and 4194303. + * This ceil operation is done by "(iround(f + .5) + iround(f - .5) + 1) >> 1", + * but uses some IEEE specific tricks for better speed. + * Contributed by Josh Vanderhoof + */ +static INLINE int iceil(float f) +{ + int ai, bi; + double af, bf; + af = (3 << 22) + 0.5 + (double)f; + bf = (3 << 22) + 0.5 - (double)f; + /* GCC generates an extra fstp/fld without this. */ + __asm__ ("fstps %0" : "=m" (ai) : "t" (af) : "st"); + __asm__ ("fstps %0" : "=m" (bi) : "t" (bf) : "st"); + return (ai - bi + 1) >> 1; +} +#define ICEIL(x) iceil(x) +#elif defined(USE_IEEE) +static INLINE int iceil(float f) +{ + int ai, bi; + double af, bf; + fi_type u; + af = (3 << 22) + 0.5 + (double)f; + bf = (3 << 22) + 0.5 - (double)f; + u.f = (float) af; ai = u.i; + u.f = (float) bf; bi = u.i; + return (ai - bi + 1) >> 1; +} +#define ICEIL(x) iceil(x) +#else +static INLINE int iceil(float f) +{ + int i = IROUND(f); + return (i < f) ? i + 1 : i; +} +#define ICEIL(x) iceil(x) +#endif + + +/** + * Is x a power of two? + */ +static INLINE int +_mesa_is_pow_two(int x) +{ + return !(x & (x - 1)); +} + +/** + * Round given integer to next higer power of two + * If X is zero result is undefined. + * + * Source for the fallback implementation is + * Sean Eron Anderson's webpage "Bit Twiddling Hacks" + * http://graphics.stanford.edu/~seander/bithacks.html + * + * When using builtin function have to do some work + * for case when passed values 1 to prevent hiting + * undefined result from __builtin_clz. Undefined + * results would be different depending on optimization + * level used for build. + */ +static INLINE int32_t +_mesa_next_pow_two_32(uint32_t x) +{ +#if defined(__GNUC__) && \ + ((__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || __GNUC__ >= 4) + uint32_t y = (x != 1); + return (1 + y) << ((__builtin_clz(x - y) ^ 31) ); +#else + x--; + x |= x >> 1; + x |= x >> 2; + x |= x >> 4; + x |= x >> 8; + x |= x >> 16; + x++; + return x; +#endif +} + +static INLINE int64_t +_mesa_next_pow_two_64(uint64_t x) +{ +#if defined(__GNUC__) && \ + ((__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || __GNUC__ >= 4) + uint64_t y = (x != 1); + if (sizeof(x) == sizeof(long)) + return (1 + y) << ((__builtin_clzl(x - y) ^ 63)); + else + return (1 + y) << ((__builtin_clzll(x - y) ^ 63)); +#else + x--; + x |= x >> 1; + x |= x >> 2; + x |= x >> 4; + x |= x >> 8; + x |= x >> 16; + x |= x >> 32; + x++; + return x; +#endif +} + + +/** + * Return 1 if this is a little endian machine, 0 if big endian. + */ +static INLINE GLboolean +_mesa_little_endian(void) +{ + const GLuint ui = 1; /* intentionally not static */ + return *((const GLubyte *) &ui); +} + + + +/********************************************************************** + * Functions + */ + +extern void * +_mesa_align_malloc( size_t bytes, unsigned long alignment ); + +extern void * +_mesa_align_calloc( size_t bytes, unsigned long alignment ); + +extern void +_mesa_align_free( void *ptr ); + +extern void * +_mesa_align_realloc(void *oldBuffer, size_t oldSize, size_t newSize, + unsigned long alignment); + +extern void * +_mesa_exec_malloc( GLuint size ); + +extern void +_mesa_exec_free( void *addr ); + +extern void * +_mesa_realloc( void *oldBuffer, size_t oldSize, size_t newSize ); + +extern void +_mesa_memset16( unsigned short *dst, unsigned short val, size_t n ); + +extern double +_mesa_sqrtd(double x); + +extern float +_mesa_sqrtf(float x); + +extern float +_mesa_inv_sqrtf(float x); + +extern void +_mesa_init_sqrt_table(void); + +#ifdef __GNUC__ +#define _mesa_ffs(i) ffs(i) +#define _mesa_ffsll(i) ffsll(i) + +#if ((_GNUC__ == 3 && __GNUC_MINOR__ >= 4) || __GNUC__ >= 4) +#define _mesa_bitcount(i) __builtin_popcount(i) +#else +extern unsigned int +_mesa_bitcount(unsigned int n); +#endif + +#else +extern int +_mesa_ffs(int32_t i); + +extern int +_mesa_ffsll(int64_t i); + +extern unsigned int +_mesa_bitcount(unsigned int n); +#endif + +extern GLhalfARB +_mesa_float_to_half(float f); + +extern float +_mesa_half_to_float(GLhalfARB h); + + +extern void * +_mesa_bsearch( const void *key, const void *base, size_t nmemb, size_t size, + int (*compar)(const void *, const void *) ); + +extern char * +_mesa_getenv( const char *var ); + +extern char * +_mesa_strdup( const char *s ); + +extern float +_mesa_strtof( const char *s, char **end ); + +extern unsigned int +_mesa_str_checksum(const char *str); + +extern int +_mesa_snprintf( char *str, size_t size, const char *fmt, ... ) PRINTFLIKE(3, 4); + +struct gl_context; + +extern void +_mesa_warning( struct gl_context *gc, const char *fmtString, ... ) PRINTFLIKE(2, 3); + +extern void +_mesa_problem( const struct gl_context *ctx, const char *fmtString, ... ) PRINTFLIKE(2, 3); + +extern void +_mesa_error( struct gl_context *ctx, GLenum error, const char *fmtString, ... ) PRINTFLIKE(3, 4); + +extern void +_mesa_debug( const struct gl_context *ctx, const char *fmtString, ... ) PRINTFLIKE(2, 3); + + +#if defined(_MSC_VER) && !defined(snprintf) +#define snprintf _snprintf +#endif + + +#ifdef __cplusplus +} +#endif + + +#endif /* IMPORTS_H */ |