Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
5564 serge 1
/*
2
 * Copyright (C) 2011 Marek Olšák 
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
 
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
 
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
 
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) {
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
 
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.0f / (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
 
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
 
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
}