1 /*
2  * Copyright (C) 2011 Marek Olšák <maraeo@gmail.com>
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21  * DEALINGS IN THE SOFTWARE.
22  */
23 
24 /* Based on code from The OpenGL Programming Guide / 7th Edition, Appendix J.
25  * Available here: http://www.opengl-redbook.com/appendices/
26  * The algorithm in the book contains a bug though, which is fixed in the code
27  * below.
28  */
29 
30 #define UF11(e, m)           ((e << 6) | (m))
31 #define UF11_EXPONENT_BIAS   15
32 #define UF11_EXPONENT_BITS   0x1F
33 #define UF11_EXPONENT_SHIFT  6
34 #define UF11_MANTISSA_BITS   0x3F
35 #define UF11_MANTISSA_SHIFT  (23 - UF11_EXPONENT_SHIFT)
36 #define UF11_MAX_EXPONENT    (UF11_EXPONENT_BITS << UF11_EXPONENT_SHIFT)
37 
38 #define UF10(e, m)           ((e << 5) | (m))
39 #define UF10_EXPONENT_BIAS   15
40 #define UF10_EXPONENT_BITS   0x1F
41 #define UF10_EXPONENT_SHIFT  5
42 #define UF10_MANTISSA_BITS   0x1F
43 #define UF10_MANTISSA_SHIFT  (23 - UF10_EXPONENT_SHIFT)
44 #define UF10_MAX_EXPONENT    (UF10_EXPONENT_BITS << UF10_EXPONENT_SHIFT)
45 
46 #define F32_INFINITY         0x7f800000
47 
f32_to_uf11(float val)48 static INLINE unsigned f32_to_uf11(float val)
49 {
50    union {
51       float f;
52       uint32_t ui;
53    } f32 = {val};
54 
55    uint16_t uf11 = 0;
56 
57    /* Decode little-endian 32-bit floating-point value */
58    int sign = (f32.ui >> 16) & 0x8000;
59    /* Map exponent to the range [-127,128] */
60    int exponent = ((f32.ui >> 23) & 0xff) - 127;
61    int mantissa = f32.ui & 0x007fffff;
62 
63    if (exponent == 128) { /* Infinity or NaN */
64       /* From the GL_EXT_packed_float spec:
65        *
66        *     "Additionally: negative infinity is converted to zero; positive
67        *      infinity is converted to positive infinity; and both positive and
68        *      negative NaN are converted to positive NaN."
69        */
70       uf11 = UF11_MAX_EXPONENT;
71       if (mantissa) {
72 	 uf11 |= 1; /* NaN */
73       } else {
74 	 if (sign)
75 	    uf11 = 0; /* 0.0 */
76       }
77    } else if (sign) {
78       return 0;
79    } else if (val > 65024.0f) {
80       /* From the GL_EXT_packed_float spec:
81        *
82        *     "Likewise, finite positive values greater than 65024 (the maximum
83        *      finite representable unsigned 11-bit floating-point value) are
84        *      converted to 65024."
85        */
86       uf11 = UF11(30, 63);
87    }
88    else if (exponent > -15) { /* Representable value */
89       exponent += UF11_EXPONENT_BIAS;
90       mantissa >>= UF11_MANTISSA_SHIFT;
91       uf11 = exponent << UF11_EXPONENT_SHIFT | mantissa;
92    }
93 
94    return uf11;
95 }
96 
uf11_to_f32(uint16_t val)97 static INLINE float uf11_to_f32(uint16_t val)
98 {
99    union {
100       float f;
101       uint32_t ui;
102    } f32;
103 
104    int exponent = (val & 0x07c0) >> UF11_EXPONENT_SHIFT;
105    int mantissa = (val & 0x003f);
106 
107    f32.f = 0.0;
108 
109    if (exponent == 0) {
110       if (mantissa != 0) {
111          const float scale = 1.0 / (1 << 20);
112          f32.f = scale * mantissa;
113       }
114    }
115    else if (exponent == 31) {
116       f32.ui = F32_INFINITY | mantissa;
117    }
118    else {
119       float scale, decimal;
120       exponent -= 15;
121       if (exponent < 0) {
122          scale = 1.0f / (1 << -exponent);
123       }
124       else {
125          scale = (float) (1 << exponent);
126       }
127       decimal = 1.0f + (float) mantissa / 64;
128       f32.f = scale * decimal;
129    }
130 
131    return f32.f;
132 }
133 
f32_to_uf10(float val)134 static INLINE unsigned f32_to_uf10(float val)
135 {
136    union {
137       float f;
138       uint32_t ui;
139    } f32 = {val};
140 
141    uint16_t uf10 = 0;
142 
143    /* Decode little-endian 32-bit floating-point value */
144    int sign = (f32.ui >> 16) & 0x8000;
145    /* Map exponent to the range [-127,128] */
146    int exponent = ((f32.ui >> 23) & 0xff) - 127;
147    int mantissa = f32.ui & 0x007fffff;
148 
149    if (exponent == 128) {
150       /* From the GL_EXT_packed_float spec:
151        *
152        *     "Additionally: negative infinity is converted to zero; positive
153        *      infinity is converted to positive infinity; and both positive and
154        *      negative NaN are converted to positive NaN."
155        */
156       uf10 = UF10_MAX_EXPONENT;
157       if (mantissa) {
158 	 uf10 |= 1; /* NaN */
159       } else {
160 	 if (sign)
161 	    uf10 = 0; /* 0.0 */
162       }
163    } else if (sign) {
164       return 0;
165    } else if (val > 64512.0f) { /* Overflow - flush to Infinity */
166       /* From the GL_EXT_packed_float spec:
167        *
168        *     "Likewise, finite positive values greater than 64512 (the maximum
169        *      finite representable unsigned 10-bit floating-point value) are
170        *      converted to 64512."
171        */
172       uf10 = UF10(30, 31);
173    }
174    else if (exponent > -15) { /* Representable value */
175       exponent += UF10_EXPONENT_BIAS;
176       mantissa >>= UF10_MANTISSA_SHIFT;
177       uf10 = exponent << UF10_EXPONENT_SHIFT | mantissa;
178    }
179 
180    return uf10;
181 }
182 
uf10_to_f32(uint16_t val)183 static INLINE float uf10_to_f32(uint16_t val)
184 {
185    union {
186       float f;
187       uint32_t ui;
188    } f32;
189 
190    int exponent = (val & 0x03e0) >> UF10_EXPONENT_SHIFT;
191    int mantissa = (val & 0x001f);
192 
193    f32.f = 0.0;
194 
195    if (exponent == 0) {
196       if (mantissa != 0) {
197          const float scale = 1.0 / (1 << 20);
198          f32.f = scale * mantissa;
199       }
200    }
201    else if (exponent == 31) {
202       f32.ui = F32_INFINITY | mantissa;
203    }
204    else {
205       float scale, decimal;
206       exponent -= 15;
207       if (exponent < 0) {
208          scale = 1.0 / (1 << -exponent);
209       }
210       else {
211          scale = (float) (1 << exponent);
212       }
213       decimal = 1.0f + (float) mantissa / 32;
214       f32.f = scale * decimal;
215    }
216 
217    return f32.f;
218 }
219 
float3_to_r11g11b10f(const float rgb[3])220 static INLINE unsigned float3_to_r11g11b10f(const float rgb[3])
221 {
222    return ( f32_to_uf11(rgb[0]) & 0x7ff) |
223           ((f32_to_uf11(rgb[1]) & 0x7ff) << 11) |
224           ((f32_to_uf10(rgb[2]) & 0x3ff) << 22);
225 }
226 
r11g11b10f_to_float3(unsigned rgb,float retval[3])227 static INLINE void r11g11b10f_to_float3(unsigned rgb, float retval[3])
228 {
229    retval[0] = uf11_to_f32( rgb        & 0x7ff);
230    retval[1] = uf11_to_f32((rgb >> 11) & 0x7ff);
231    retval[2] = uf10_to_f32((rgb >> 22) & 0x3ff);
232 }
233