xref: /aosp_15_r20/external/mesa3d/src/util/format_r11g11b10f.h (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /*
2  * Copyright (C) 2011 Marek Olšák <[email protected]>
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 #ifndef FORMAT_R11G11B10F_H
31 #define FORMAT_R11G11B10F_H
32 
33 #include <stdint.h>
34 
35 #include "rounding.h"
36 
37 #define UF11(e, m)           ((e << 6) | (m))
38 #define UF11_EXPONENT_BIAS   15
39 #define UF11_EXPONENT_BITS   0x1F
40 #define UF11_EXPONENT_SHIFT  6
41 #define UF11_MANTISSA_BITS   0x3F
42 #define UF11_MANTISSA_SHIFT  (23 - UF11_EXPONENT_SHIFT)
43 #define UF11_MAX_EXPONENT    (UF11_EXPONENT_BITS << UF11_EXPONENT_SHIFT)
44 
45 #define UF10(e, m)           ((e << 5) | (m))
46 #define UF10_EXPONENT_BIAS   15
47 #define UF10_EXPONENT_BITS   0x1F
48 #define UF10_EXPONENT_SHIFT  5
49 #define UF10_MANTISSA_BITS   0x1F
50 #define UF10_MANTISSA_SHIFT  (23 - UF10_EXPONENT_SHIFT)
51 #define UF10_MAX_EXPONENT    (UF10_EXPONENT_BITS << UF10_EXPONENT_SHIFT)
52 
53 #define F32_INFINITY         0x7f800000
54 
f32_to_uf11(float val)55 static inline uint32_t f32_to_uf11(float val)
56 {
57    union {
58       float f;
59       uint32_t ui;
60    } f32 = {val};
61 
62    uint16_t uf11 = 0;
63 
64    /* Decode little-endian 32-bit floating-point value */
65    int sign = (f32.ui >> 16) & 0x8000;
66    /* Map exponent to the range [-127,128] */
67    int exponent = ((f32.ui >> 23) & 0xff) - 127;
68    int mantissa = f32.ui & 0x007fffff;
69 
70    if (exponent == 128) { /* Infinity or NaN */
71       /* From the GL_EXT_packed_float spec:
72        *
73        *     "Additionally: negative infinity is converted to zero; positive
74        *      infinity is converted to positive infinity; and both positive and
75        *      negative NaN are converted to positive NaN."
76        */
77       uf11 = UF11_MAX_EXPONENT;
78       if (mantissa) {
79          uf11 |= 1; /* NaN */
80       } else {
81          if (sign)
82             uf11 = 0; /* 0.0 */
83       }
84    } else if (sign) {
85       return 0;
86    } else if (val > 65024.0f) {
87       /* From the GL_EXT_packed_float spec:
88        *
89        *     "Likewise, finite positive values greater than 65024 (the maximum
90        *      finite representable unsigned 11-bit floating-point value) are
91        *      converted to 65024."
92        */
93       uf11 = UF11(30, 63);
94    } else if (exponent > -15) { /* Normal value */
95       /* Dividing by 2^exponent gives us a number in the range [1, 2).
96        * Multiplying by 2^6=64 gives us our mantissa, plus an extra 1 which
97        * we'll mask off.
98        */
99       mantissa = _mesa_lroundevenf(ldexp(val, 6 - exponent));
100       if (mantissa >= 2 << UF11_EXPONENT_SHIFT) {
101          /* The float32 was rounded upwards into the range of the next
102           * exponent, so bump the exponent.
103           */
104          assert(mantissa == 2 << UF11_EXPONENT_SHIFT);
105          mantissa >>= 1;
106          exponent++;
107       }
108       assert((mantissa >> UF11_EXPONENT_SHIFT) == 1);
109       mantissa &= UF11_MANTISSA_BITS;
110       exponent += UF11_EXPONENT_BIAS;
111       uf11 = UF11(exponent, mantissa);
112    } else { /* Zero or denormal */
113       /* Since exponent <= -15, Multiplying by 2^14 gives us a number in the
114        * range [0, 1). Multiplying by 2^6=64 gives us our mantissa.
115        */
116       mantissa = _mesa_lroundevenf(ldexp(val, 6 + 14));
117 
118       /* It's possible that we get a normal after rounding */
119       if ((mantissa >> UF11_EXPONENT_SHIFT) != 0) {
120          assert(mantissa == (1 << UF11_EXPONENT_SHIFT));
121          uf11 = UF11(1, 0);
122       } else {
123          uf11 = UF11(0, mantissa);
124       }
125    }
126 
127    return uf11;
128 }
129 
uf11_to_f32(uint16_t val)130 static inline float uf11_to_f32(uint16_t val)
131 {
132    union {
133       float f;
134       uint32_t ui;
135    } f32;
136 
137    int exponent = (val & 0x07c0) >> UF11_EXPONENT_SHIFT;
138    int mantissa = (val & 0x003f);
139 
140    f32.f = 0.0;
141 
142    if (exponent == 0) {
143       if (mantissa != 0) {
144          const float scale = 1.0 / (1 << 20);
145          f32.f = scale * mantissa;
146       }
147    } else if (exponent == 31) {
148       f32.ui = F32_INFINITY | mantissa;
149    } else {
150       float scale, decimal;
151       exponent -= 15;
152       if (exponent < 0) {
153          scale = 1.0f / (1 << -exponent);
154       } else {
155          scale = (float) (1 << exponent);
156       }
157       decimal = 1.0f + (float) mantissa / 64;
158       f32.f = scale * decimal;
159    }
160 
161    return f32.f;
162 }
163 
f32_to_uf10(float val)164 static inline uint32_t f32_to_uf10(float val)
165 {
166    union {
167       float f;
168       uint32_t ui;
169    } f32 = {val};
170 
171    uint16_t uf10 = 0;
172 
173    /* Decode little-endian 32-bit floating-point value */
174    int sign = (f32.ui >> 16) & 0x8000;
175    /* Map exponent to the range [-127,128] */
176    int exponent = ((f32.ui >> 23) & 0xff) - 127;
177    int mantissa = f32.ui & 0x007fffff;
178 
179    if (exponent == 128) {
180       /* From the GL_EXT_packed_float spec:
181        *
182        *     "Additionally: negative infinity is converted to zero; positive
183        *      infinity is converted to positive infinity; and both positive and
184        *      negative NaN are converted to positive NaN."
185        */
186       uf10 = UF10_MAX_EXPONENT;
187       if (mantissa) {
188          uf10 |= 1; /* NaN */
189       } else {
190          if (sign)
191             uf10 = 0; /* 0.0 */
192       }
193    } else if (sign) {
194       return 0;
195    } else if (val > 64512.0f) {
196       /* From the GL_EXT_packed_float spec:
197        *
198        *     "Likewise, finite positive values greater than 64512 (the maximum
199        *      finite representable unsigned 10-bit floating-point value) are
200        *      converted to 64512."
201        */
202       uf10 = UF10(30, 31);
203    } else if (exponent > -15) { /* Normal value */
204       /* Dividing by 2^exponent gives us a number in the range [1, 2).
205        * Multiplying by 2^5=32 gives us our mantissa, plus an extra 1 which
206        * we'll mask off.
207        */
208       mantissa = _mesa_lroundevenf(ldexp(val, 5 - exponent));
209       if (mantissa >= 2 << UF10_EXPONENT_SHIFT) {
210          /* The float32 was rounded upwards into the range of the next
211           * exponent, so bump the exponent.
212           */
213          assert(mantissa == 2 << UF10_EXPONENT_SHIFT);
214          mantissa >>= 1;
215          exponent++;
216       }
217       assert((mantissa >> UF10_EXPONENT_SHIFT) == 1);
218       mantissa &= UF10_MANTISSA_BITS;
219       exponent += UF10_EXPONENT_BIAS;
220       uf10 = UF10(exponent, mantissa);
221    } else { /* Zero or denormal */
222       /* Since exponent <= -15, Multiplying by 2^14 gives us a number in the
223        * range [0, 1). Multiplying by 2^5=32 gives us our mantissa.
224        */
225       mantissa = _mesa_lroundevenf(ldexp(val, 5 + 14));
226 
227       /* It's possible that we get a normal after rounding */
228       if ((mantissa >> UF10_EXPONENT_SHIFT) != 0) {
229          assert(mantissa == (1 << UF10_EXPONENT_SHIFT));
230          uf10 = UF10(1, 0);
231       } else {
232          uf10 = UF10(0, mantissa);
233       }
234    }
235 
236    return uf10;
237 }
238 
uf10_to_f32(uint16_t val)239 static inline float uf10_to_f32(uint16_t val)
240 {
241    union {
242       float f;
243       uint32_t ui;
244    } f32;
245 
246    int exponent = (val & 0x03e0) >> UF10_EXPONENT_SHIFT;
247    int mantissa = (val & 0x001f);
248 
249    f32.f = 0.0;
250 
251    if (exponent == 0) {
252       if (mantissa != 0) {
253          const float scale = 1.0 / (1 << 19);
254          f32.f = scale * mantissa;
255       }
256    } else if (exponent == 31) {
257       f32.ui = F32_INFINITY | mantissa;
258    } else {
259       float scale, decimal;
260       exponent -= 15;
261       if (exponent < 0) {
262          scale = 1.0f / (1 << -exponent);
263       }
264       else {
265          scale = (float) (1 << exponent);
266       }
267       decimal = 1.0f + (float) mantissa / 32;
268       f32.f = scale * decimal;
269    }
270 
271    return f32.f;
272 }
273 
float3_to_r11g11b10f(const float rgb[3])274 static inline uint32_t float3_to_r11g11b10f(const float rgb[3])
275 {
276    return ( f32_to_uf11(rgb[0]) & 0x7ff) |
277           ((f32_to_uf11(rgb[1]) & 0x7ff) << 11) |
278           ((f32_to_uf10(rgb[2]) & 0x3ff) << 22);
279 }
280 
r11g11b10f_to_float3(uint32_t rgb,float retval[3])281 static inline void r11g11b10f_to_float3(uint32_t rgb, float retval[3])
282 {
283    retval[0] = uf11_to_f32( rgb        & 0x7ff);
284    retval[1] = uf11_to_f32((rgb >> 11) & 0x7ff);
285    retval[2] = uf10_to_f32((rgb >> 22) & 0x3ff);
286 }
287 
288 #endif /* FORMAT_R11G11B10F_H */
289