diff options
Diffstat (limited to 'opengl/libagl/fp.h')
-rw-r--r-- | opengl/libagl/fp.h | 243 |
1 files changed, 243 insertions, 0 deletions
diff --git a/opengl/libagl/fp.h b/opengl/libagl/fp.h new file mode 100644 index 0000000..6d0c183 --- /dev/null +++ b/opengl/libagl/fp.h @@ -0,0 +1,243 @@ +/* libs/opengles/fp.h +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + +#ifndef ANDROID_OPENGLES_FP_H +#define ANDROID_OPENGLES_FP_H + +#include <stdint.h> +#include <stddef.h> +#include <sys/types.h> +#include <math.h> + +#include <private/pixelflinger/ggl_context.h> + +#include <GLES/gl.h> + +#define DEBUG_USE_FLOATS 0 + +// ---------------------------------------------------------------------------- + +extern "C" GLfixed gglFloatToFixed(float f) __attribute__((const)); + +// ---------------------------------------------------------------------------- +namespace android { + +namespace gl { + + GLfloat fixedToFloat(GLfixed) CONST; + + void sincosf(GLfloat angle, GLfloat* s, GLfloat* c); + float sinef(GLfloat x) CONST; + float cosinef(GLfloat x) CONST; + +inline bool cmpf(GLfloat a, GLfloat b) CONST; +inline bool isZerof(GLfloat) CONST; +inline bool isOnef(GLfloat) CONST; + +inline int isZeroOrNegativef(GLfloat) CONST; + +inline int exponent(GLfloat) CONST; +inline int32_t mantissa(GLfloat) CONST; +inline GLfloat clampToZerof(GLfloat) CONST; +inline GLfloat reciprocalf(GLfloat) CONST; +inline GLfloat rsqrtf(GLfloat) CONST; +inline GLfloat sqrf(GLfloat) CONST; +inline GLfloat addExpf(GLfloat v, int e) CONST; +inline GLfloat mul2f(GLfloat v) CONST; +inline GLfloat div2f(GLfloat v) CONST; +inline GLfloat absf(GLfloat v) CONST; + + +/* + * float fastexpf(float) : a fast approximation of expf(x) + * give somewhat accurate results for -88 <= x <= 88 + * + * exp(x) = 2^(x/ln(2)) + * we use the properties of float encoding + * to get a fast 2^ and linear interpolation + * + */ + +inline float fastexpf(float y) __attribute__((const)); + +inline float fastexpf(float y) +{ + union { + float r; + int32_t i; + } u; + + // 127*ln(2) = 88 + if (y < -88.0f) { + u.r = 0.0f; + } else if (y > 88.0f) { + u.r = INFINITY; + } else { + const float kOneOverLogTwo = (1L<<23) / M_LN2; + const int32_t kExponentBias = 127L<<23; + const int32_t e = int32_t(y*kOneOverLogTwo); + u.i = e + kExponentBias; + } + + return u.r; +} + + +bool cmpf(GLfloat a, GLfloat b) { +#if DEBUG_USE_FLOATS + return a == b; +#else + union { + float f; + uint32_t i; + } ua, ub; + ua.f = a; + ub.f = b; + return ua.i == ub.i; +#endif +} + +bool isZerof(GLfloat v) { +#if DEBUG_USE_FLOATS + return v == 0; +#else + union { + float f; + int32_t i; + }; + f = v; + return (i<<1) == 0; +#endif +} + +bool isOnef(GLfloat v) { + return cmpf(v, 1.0f); +} + +int isZeroOrNegativef(GLfloat v) { +#if DEBUG_USE_FLOATS + return v <= 0; +#else + union { + float f; + int32_t i; + }; + f = v; + return isZerof(v) | (i>>31); +#endif +} + +int exponent(GLfloat v) { + union { + float f; + uint32_t i; + }; + f = v; + return ((i << 1) >> 24) - 127; +} + +int32_t mantissa(GLfloat v) { + union { + float f; + uint32_t i; + }; + f = v; + if (!(i&0x7F800000)) return 0; + const int s = i >> 31; + i |= (1L<<23); + i &= ~0xFF000000; + return s ? -i : i; +} + +GLfloat clampToZerof(GLfloat v) { +#if DEBUG_USE_FLOATS + return v<0 ? 0 : (v>1 ? 1 : v); +#else + union { + float f; + int32_t i; + }; + f = v; + i &= ~(i>>31); + return f; +#endif +} + +GLfloat reciprocalf(GLfloat v) { + // XXX: do better + return 1.0f / v; +} + +GLfloat rsqrtf(GLfloat v) { + // XXX: do better + return 1.0f / sqrtf(v); +} + +GLfloat sqrf(GLfloat v) { + // XXX: do better + return v*v; +} + +GLfloat addExpf(GLfloat v, int e) { + union { + float f; + int32_t i; + }; + f = v; + if (i<<1) { // XXX: deal with over/underflow + i += int32_t(e)<<23; + } + return f; +} + +GLfloat mul2f(GLfloat v) { +#if DEBUG_USE_FLOATS + return v*2; +#else + return addExpf(v, 1); +#endif +} + +GLfloat div2f(GLfloat v) { +#if DEBUG_USE_FLOATS + return v*0.5f; +#else + return addExpf(v, -1); +#endif +} + +GLfloat absf(GLfloat v) { +#if DEBUG_USE_FLOATS + return v<0 ? -v : v; +#else + union { + float f; + int32_t i; + }; + f = v; + i &= ~0x80000000; + return f; +#endif +} + +}; // namespace gl + +// ---------------------------------------------------------------------------- +}; // namespace android + +#endif // ANDROID_OPENGLES_FP_H + |