u_format_r11g11b10f.h revision 00d3716f4a91145609f50aa56de53e175d1c8b49
1a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)/* 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Copyright (C) 2011 Marek Olšák <maraeo@gmail.com> 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Permission is hereby granted, free of charge, to any person obtaining a 5a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) * copy of this software and associated documentation files (the "Software"), 6a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) * to deal in the Software without restriction, including without limitation 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * the rights to use, copy, modify, merge, publish, distribute, sublicense, 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * and/or sell copies of the Software, and to permit persons to whom the 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Software is furnished to do so, subject to the following conditions: 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 11a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) * The above copyright notice and this permission notice (including the next 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * paragraph) shall be included in all copies or substantial portions of the 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Software. 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * DEALINGS IN THE SOFTWARE. 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Based on code from The OpenGL Programming Guide / 7th Edition, Appendix J. 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Available here: http://www.opengl-redbook.com/appendices/ 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The algorithm in the book contains a bug though, which is fixed in the code 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * below. 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define UF11(e, m) ((e << 6) | (m)) 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define UF11_EXPONENT_BIAS 15 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define UF11_EXPONENT_BITS 0x1F 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define UF11_EXPONENT_SHIFT 6 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define UF11_MANTISSA_BITS 0x3F 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define UF11_MANTISSA_SHIFT (23 - UF11_EXPONENT_SHIFT) 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define UF11_MAX_EXPONENT (UF11_EXPONENT_BITS << UF11_EXPONENT_SHIFT) 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define UF10(e, m) ((e << 5) | (m)) 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define UF10_EXPONENT_BIAS 15 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define UF10_EXPONENT_BITS 0x1F 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define UF10_EXPONENT_SHIFT 5 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define UF10_MANTISSA_BITS 0x1F 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define UF10_MANTISSA_SHIFT (23 - UF10_EXPONENT_SHIFT) 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define UF10_MAX_EXPONENT (UF10_EXPONENT_BITS << UF10_EXPONENT_SHIFT) 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define F32_INFINITY 0x7f800000 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static INLINE unsigned f32_to_uf11(float val) 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) union { 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) float f; 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint32_t ui; 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } f32 = {val}; 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint16_t uf11 = 0; 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 57a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) /* 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 (sign) return 0; 64 65 if (exponent == 128) { /* Infinity or NaN */ 66 uf11 = UF11_MAX_EXPONENT; 67 if (mantissa) uf11 |= (mantissa & UF11_MANTISSA_BITS); 68 } 69 else if (val > 65024.0f) { 70 /* From the GL_EXT_packed_float spec: 71 * 72 * "Likewise, finite positive values greater than 65024 (the maximum 73 * finite representable unsigned 11-bit floating-point value) are 74 * converted to 65024." 75 */ 76 uf11 = UF11(30, 63); 77 } 78 else if (exponent > -15) { /* Representable value */ 79 exponent += UF11_EXPONENT_BIAS; 80 mantissa >>= UF11_MANTISSA_SHIFT; 81 uf11 = exponent << UF11_EXPONENT_SHIFT | mantissa; 82 } 83 84 return uf11; 85} 86 87static INLINE float uf11_to_f32(uint16_t val) 88{ 89 union { 90 float f; 91 uint32_t ui; 92 } f32; 93 94 int exponent = (val & 0x07c0) >> UF11_EXPONENT_SHIFT; 95 int mantissa = (val & 0x003f); 96 97 f32.f = 0.0; 98 99 if (exponent == 0) { 100 if (mantissa != 0) { 101 const float scale = 1.0 / (1 << 20); 102 f32.f = scale * mantissa; 103 } 104 } 105 else if (exponent == 31) { 106 f32.ui = F32_INFINITY | mantissa; 107 } 108 else { 109 float scale, decimal; 110 exponent -= 15; 111 if (exponent < 0) { 112 scale = 1.0 / (1 << -exponent); 113 } 114 else { 115 scale = 1 << exponent; 116 } 117 decimal = 1.0 + (float) mantissa / 64; 118 f32.f = scale * decimal; 119 } 120 121 return f32.f; 122} 123 124static INLINE unsigned f32_to_uf10(float val) 125{ 126 union { 127 float f; 128 uint32_t ui; 129 } f32 = {val}; 130 131 uint16_t uf10 = 0; 132 133 /* Decode little-endian 32-bit floating-point value */ 134 int sign = (f32.ui >> 16) & 0x8000; 135 /* Map exponent to the range [-127,128] */ 136 int exponent = ((f32.ui >> 23) & 0xff) - 127; 137 int mantissa = f32.ui & 0x007fffff; 138 139 if (sign) return 0; 140 141 if (exponent == 128) { /* Infinity or NaN */ 142 uf10 = UF10_MAX_EXPONENT; 143 if (mantissa) uf10 |= (mantissa & UF10_MANTISSA_BITS); 144 } 145 else if (val > 64512.0f) { /* Overflow - flush to Infinity */ 146 /* From the GL_EXT_packed_float spec: 147 * 148 * "Likewise, finite positive values greater than 64512 (the maximum 149 * finite representable unsigned 10-bit floating-point value) are 150 * converted to 64512." 151 */ 152 uf10 = UF10(30, 31); 153 } 154 else if (exponent > -15) { /* Representable value */ 155 exponent += UF10_EXPONENT_BIAS; 156 mantissa >>= UF10_MANTISSA_SHIFT; 157 uf10 = exponent << UF10_EXPONENT_SHIFT | mantissa; 158 } 159 160 return uf10; 161} 162 163static INLINE float uf10_to_f32(uint16_t val) 164{ 165 union { 166 float f; 167 uint32_t ui; 168 } f32; 169 170 int exponent = (val & 0x03e0) >> UF10_EXPONENT_SHIFT; 171 int mantissa = (val & 0x001f); 172 173 f32.f = 0.0; 174 175 if (exponent == 0) { 176 if (mantissa != 0) { 177 const float scale = 1.0 / (1 << 20); 178 f32.f = scale * mantissa; 179 } 180 } 181 else if (exponent == 31) { 182 f32.ui = F32_INFINITY | mantissa; 183 } 184 else { 185 float scale, decimal; 186 exponent -= 15; 187 if (exponent < 0) { 188 scale = 1.0 / (1 << -exponent); 189 } 190 else { 191 scale = 1 << exponent; 192 } 193 decimal = 1.0 + (float) mantissa / 32; 194 f32.f = scale * decimal; 195 } 196 197 return f32.f; 198} 199 200static INLINE unsigned float3_to_r11g11b10f(const float rgb[3]) 201{ 202 return ( f32_to_uf11(rgb[0]) & 0x7ff) | 203 ((f32_to_uf11(rgb[1]) & 0x7ff) << 11) | 204 ((f32_to_uf10(rgb[2]) & 0x3ff) << 22); 205} 206 207static INLINE void r11g11b10f_to_float3(unsigned rgb, float retval[3]) 208{ 209 retval[0] = uf11_to_f32( rgb & 0x7ff); 210 retval[1] = uf11_to_f32((rgb >> 11) & 0x7ff); 211 retval[2] = uf10_to_f32((rgb >> 22) & 0x3ff); 212} 213