+#include <Moof/Math.hh>
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+
+// generic function arguments
+
+#define ARGS_P const GLscalar* p
+#define PASS_P p
+
+#define ARGS_M const Mf::Matrix4& m
+#define PASS_M m.data()
+
+// ordinal function arguments
+
+#define ARGS_S2 GLscalar a, GLscalar b
+#define PASS_S2 a, b
+#define ARGS_S3 GLscalar a, GLscalar b, GLscalar c
+#define PASS_S3 a, b, c
+#define ARGS_S4 GLscalar a, GLscalar b, GLscalar c, GLscalar d
+#define PASS_S4 a, b, c, d
+
+#define ARGS_P2 const Mf::Vector2& p
+#define PASS_P2 p.data()
+#define ARGS_P3 const Mf::Vector3& p
+#define PASS_P3 p.data()
+#define ARGS_P4 const Mf::Vector4& p
+#define PASS_P4 p.data()
+
+#define ARGS_V2 const Mf::Vector2& v
+#define PASS_V2 v[0], v[1]
+#define ARGS_V3 const Mf::Vector3& v
+#define PASS_V3 v[0], v[1], v[2]
+#define ARGS_V4 const Mf::Vector4& v
+#define PASS_V4 v[0], v[1], v[2], v[3]
+
+
+#if USE_DOUBLE_PRECISION
+
+#define OPENGL_GENERIC_FUNC(R, N, L) \
+ inline R gl##N(ARGS_##L) { gl##N##d(PASS_##L); }//
+
+#define OPENGL_ORDINAL_FUNC(R, N, K) \
+ inline R gl##N(ARGS_##S##K) { gl##N##K##d(PASS_##S##K); } \
+ inline R gl##N(ARGS_##P##K) { gl##N##K##d##v(PASS_##P##K); }//
+
+#else
+
+#define OPENGL_GENERIC_FUNC(R, N, L) \
+ inline R gl##N(ARGS_##L) { gl##N##f(PASS_##L); }//
+
+#define OPENGL_ORDINAL_FUNC(R, N, K) \
+ inline R gl##N(ARGS_##S##K) { gl##N##K##f(PASS_##S##K); } \
+ inline R gl##N(ARGS_##P##K) { gl##N##K##f##v(PASS_##P##K); }//
+
+#endif
+
+
+OPENGL_GENERIC_FUNC(void, LoadMatrix, P);
+OPENGL_GENERIC_FUNC(void, LoadMatrix, M);
+OPENGL_GENERIC_FUNC(void, MultMatrix, P);
+OPENGL_GENERIC_FUNC(void, MultMatrix, M);
+
+OPENGL_GENERIC_FUNC(void, Scale, S3);
+OPENGL_GENERIC_FUNC(void, Scale, V3);
+OPENGL_GENERIC_FUNC(void, Rotate, S4);
+OPENGL_GENERIC_FUNC(void, Rotate, V4);
+OPENGL_GENERIC_FUNC(void, Translate, S3);
+OPENGL_GENERIC_FUNC(void, Translate, V3);
+
+OPENGL_ORDINAL_FUNC(void, Color, 3);
+OPENGL_ORDINAL_FUNC(void, Color, 4);
+
+OPENGL_ORDINAL_FUNC(void, Vertex, 2);
+OPENGL_ORDINAL_FUNC(void, Vertex, 3);
+OPENGL_ORDINAL_FUNC(void, Vertex, 4);
+
+OPENGL_ORDINAL_FUNC(void, TexCoord, 2);
+OPENGL_ORDINAL_FUNC(void, TexCoord, 3);
+OPENGL_ORDINAL_FUNC(void, TexCoord, 4);
+
+
+#if USE_DOUBLE_PRECISION
+inline void glGetScalar(GLenum a, GLscalar* b) { glGetDoublev(a, b); }
+#else
+inline void glGetScalar(GLenum a, GLscalar* b) { glGetFloatv(a, b); }
+#endif
+
+