244 lines
4.7 KiB
C++
244 lines
4.7 KiB
C++
/* 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
|
|
|