diff --git a/GL/draw.c b/GL/draw.c index 01d9cf7..129226e 100644 --- a/GL/draw.c +++ b/GL/draw.c @@ -8,6 +8,31 @@ #include "private.h" #include "platform.h" +GLushort _quantize( GLfloat v ) { + union { GLfloat f; GLuint ui; } u = {v}; + GLuint ui = u.ui; + + int s = (ui >> 16) & 0x8000; + int em = ui & 0x7fffffff; + + int h = (em - (112 << 23) + (1 << 12)) >> 13; + h = (em < (113 << 23)) ? 0 : h; + h = (em >= (143 << 23)) ? 0x7c00 : h; + h = (em > (255 << 23)) ? 0x7e00 : h; + + return (GLushort)(s | h); +} +GLfloat _dequantize( GLushort h ) { + GLuint s = (GLuint) (h & 0x8000) << 16; + int em = h & 0x7fff; + int r = (em + (112 << 10)) << 13; + r = (em < (1 << 10)) ? 0 : r; + r += (em >= (31 << 10)) ? (112 << 23) : 0; + + union { GLfloat f; GLuint ui; } u; + u.ui = s | r; + return u.f; +} AttribPointerList ATTRIB_POINTERS; GLuint ENABLED_VERTEX_ATTRIBUTES = 0; @@ -63,6 +88,7 @@ GL_FORCE_INLINE GLsizei byte_size(GLenum type) { case GL_INT: return sizeof(GLint); case GL_UNSIGNED_INT: return sizeof(GLuint); case GL_DOUBLE: return sizeof(GLdouble); + case GL_HALF_FLOAT: return sizeof(GLhalf); case GL_UNSIGNED_INT_2_10_10_10_REV: return sizeof(GLuint); case GL_FLOAT: default: return sizeof(GLfloat); @@ -109,6 +135,15 @@ static void _readVertexData3us3f(const GLubyte* in, GLubyte* out) { output[2] = input[2]; } +static void _readVertexData3usq3f(const GLubyte* in, GLubyte* out) { + const GLushort* input = (const GLushort*) in; + float* output = (float*) out; + + output[0] = _dequantize(input[0]); + output[1] = _dequantize(input[1]); + output[2] = _dequantize(input[2]); +} + static void _readVertexData3ui3f(const GLubyte* in, GLubyte* out) { const GLuint* input = (const GLuint*) in; float* output = (float*) out; @@ -127,6 +162,15 @@ static void _readVertexData3ub3f(const GLubyte* input, GLubyte* out) { output[2] = input[2] * ONE_OVER_TWO_FIVE_FIVE; } +static void _readVertexData3f16_3f(const GLubyte* in, GLubyte* out) { + const GLhalf* input = (const GLhalf*) in; + float* output = (float*) out; + + output[0] = input[0]; + output[1] = input[1]; + output[2] = input[2]; +} + static void _readVertexData2f2f(const GLubyte* in, GLubyte* out) { vec2cpy(out, in); } @@ -164,6 +208,23 @@ static void _readVertexData2us2f(const GLubyte* in, GLubyte* out) { output[1] = (float)input[1] / SHRT_MAX; } +static void _readVertexData2usq3f(const GLubyte* in, GLubyte* out) { + const GLushort* input = (const GLushort*) in; + float* output = (float*) out; + + output[0] = _dequantize(input[0]); + output[1] = _dequantize(input[1]); + output[2] = 0.0f; +} + +static void _readVertexData2usq2f(const GLubyte* in, GLubyte* out) { + const GLushort* input = (const GLushort*) in; + float* output = (float*) out; + + output[0] = _dequantize(input[0]); + output[1] = _dequantize(input[1]); +} + static void _readVertexData2ui2f(const GLubyte* in, GLubyte* out) { const GLuint* input = (const GLuint*) in; float* output = (float*) out; @@ -179,6 +240,14 @@ static void _readVertexData2ub2f(const GLubyte* input, GLubyte* out) { output[1] = input[1] * ONE_OVER_TWO_FIVE_FIVE; } +static void _readVertexData2f16_2f(const GLubyte* in, GLubyte* out) { + const GLhalf* input = (const GLhalf*) in; + float* output = (float*) out; + + output[0] = input[0]; + output[1] = input[1]; +} + static void _readVertexData2ui3f(const GLubyte* in, GLubyte* out) { const GLuint* input = (const GLuint*) in; float* output = (float*) out; @@ -188,6 +257,15 @@ static void _readVertexData2ui3f(const GLubyte* in, GLubyte* out) { output[2] = 0.0f; } +static void _readVertexData2f16_3f(const GLubyte* in, GLubyte* out) { + const GLhalf* input = (const GLhalf*) in; + float* output = (float*) out; + + output[0] = input[0]; + output[1] = input[1]; + output[2] = 0.0f; +} + static void _readVertexData4ubARGB(const GLubyte* input, GLubyte* output) { output[R8IDX] = input[0]; output[G8IDX] = input[1]; @@ -493,14 +571,17 @@ ReadPositionFunc calcReadPositionFunc() { case GL_FLOAT: return (ATTRIB_POINTERS.vertex.size == 3) ? _readVertexData3f3f: _readVertexData2f3f; + case GL_HALF_FLOAT: + return (ATTRIB_POINTERS.vertex.size == 3) ? _readVertexData3f16_3f: + _readVertexData2f16_3f; case GL_BYTE: case GL_UNSIGNED_BYTE: return (ATTRIB_POINTERS.vertex.size == 3) ? _readVertexData3ub3f: _readVertexData2ub3f; case GL_SHORT: case GL_UNSIGNED_SHORT: - return (ATTRIB_POINTERS.vertex.size == 3) ? _readVertexData3us3f: - _readVertexData2us3f; + return (ATTRIB_POINTERS.vertex.size == 3) ? _readVertexData3usq3f: + _readVertexData2usq3f; case GL_INT: case GL_UNSIGNED_INT: return (ATTRIB_POINTERS.vertex.size == 3) ? _readVertexData3ui3f: @@ -518,12 +599,14 @@ ReadUVFunc calcReadUVFunc() { case GL_DOUBLE: case GL_FLOAT: return _readVertexData2f2f; + case GL_HALF_FLOAT: + return _readVertexData2f16_2f; case GL_BYTE: case GL_UNSIGNED_BYTE: return _readVertexData2ub2f; case GL_SHORT: case GL_UNSIGNED_SHORT: - return _readVertexData2us2f; + return _readVertexData2usq2f; case GL_INT: case GL_UNSIGNED_INT: return _readVertexData2ui2f; @@ -540,12 +623,14 @@ ReadUVFunc calcReadSTFunc() { case GL_DOUBLE: case GL_FLOAT: return _readVertexData2f2f; + case GL_HALF_FLOAT: + return _readVertexData2f16_2f; case GL_BYTE: case GL_UNSIGNED_BYTE: return _readVertexData2ub2f; case GL_SHORT: case GL_UNSIGNED_SHORT: - return _readVertexData2us2f; + return _readVertexData2usq2f; case GL_INT: case GL_UNSIGNED_INT: return _readVertexData2ui2f; @@ -562,6 +647,8 @@ ReadNormalFunc calcReadNormalFunc() { case GL_DOUBLE: case GL_FLOAT: return _readVertexData3f3f; + case GL_HALF_FLOAT: + return _readVertexData3f16_3f; break; case GL_BYTE: case GL_UNSIGNED_BYTE: @@ -569,7 +656,7 @@ ReadNormalFunc calcReadNormalFunc() { break; case GL_SHORT: case GL_UNSIGNED_SHORT: - return _readVertexData3us3f; + return _readVertexData3usq3f; break; case GL_INT: case GL_UNSIGNED_INT: diff --git a/include/GL/gl.h b/include/GL/gl.h index 028f900..040acc2 100644 --- a/include/GL/gl.h +++ b/include/GL/gl.h @@ -19,6 +19,10 @@ __BEGIN_DECLS #include +#if __STDCPP_FLOAT16_T__ + #include +#endif + /* Primitive Types taken from GL for compatability */ /* Not all types are implemented in Open GL DC V.1.0 */ #define GL_POINTS 0x0000 @@ -305,6 +309,7 @@ __BEGIN_DECLS #define GL_UNSIGNED_INT 0x1405 #define GL_FLOAT 0x1406 #define GL_DOUBLE 0x140A +#define GL_HALF_FLOAT 0x140B #define GL_2_BYTES 0x1407 #define GL_3_BYTES 0x1408 #define GL_4_BYTES 0x1409 @@ -461,6 +466,12 @@ __BEGIN_DECLS #define GL_FALSE 0 #define GL_TRUE 1 +#if __STDCPP_FLOAT16_T__ +#define GLhalf std::float16_t +#else +#define GLhalf unsigned short +#endif + /* Stubs for portability */ #define GL_LINE_SMOOTH 0x0B20 #define GL_ALPHA_TEST 0x0BC0