Line data Source code
1 : //
2 : // Copyright (c) 2013 The ANGLE Project Authors. All rights reserved.
3 : // Use of this source code is governed by a BSD-style license that can be
4 : // found in the LICENSE file.
5 : //
6 :
7 : // mathutil.cpp: Math and bit manipulation functions.
8 :
9 : #include "common/mathutil.h"
10 :
11 : #include <algorithm>
12 : #include <math.h>
13 :
14 : namespace gl
15 : {
16 :
17 : namespace
18 : {
19 :
20 : struct RGB9E5Data
21 : {
22 : unsigned int R : 9;
23 : unsigned int G : 9;
24 : unsigned int B : 9;
25 : unsigned int E : 5;
26 : };
27 :
28 : // B is the exponent bias (15)
29 : constexpr int g_sharedexp_bias = 15;
30 :
31 : // N is the number of mantissa bits per component (9)
32 : constexpr int g_sharedexp_mantissabits = 9;
33 :
34 : // Emax is the maximum allowed biased exponent value (31)
35 : constexpr int g_sharedexp_maxexponent = 31;
36 :
37 : constexpr float g_sharedexp_max =
38 : ((static_cast<float>(1 << g_sharedexp_mantissabits) - 1) /
39 : static_cast<float>(1 << g_sharedexp_mantissabits)) *
40 : static_cast<float>(1 << (g_sharedexp_maxexponent - g_sharedexp_bias));
41 :
42 : } // anonymous namespace
43 :
44 0 : unsigned int convertRGBFloatsTo999E5(float red, float green, float blue)
45 : {
46 0 : const float red_c = std::max<float>(0, std::min(g_sharedexp_max, red));
47 0 : const float green_c = std::max<float>(0, std::min(g_sharedexp_max, green));
48 0 : const float blue_c = std::max<float>(0, std::min(g_sharedexp_max, blue));
49 :
50 0 : const float max_c = std::max<float>(std::max<float>(red_c, green_c), blue_c);
51 0 : const float exp_p = std::max<float>(-g_sharedexp_bias - 1, floor(log(max_c))) + 1 + g_sharedexp_bias;
52 0 : const int max_s = static_cast<int>(floor((max_c / (pow(2.0f, exp_p - g_sharedexp_bias - g_sharedexp_mantissabits))) + 0.5f));
53 0 : const int exp_s = static_cast<int>((max_s < pow(2.0f, g_sharedexp_mantissabits)) ? exp_p : exp_p + 1);
54 :
55 : RGB9E5Data output;
56 0 : output.R = static_cast<unsigned int>(floor((red_c / (pow(2.0f, exp_s - g_sharedexp_bias - g_sharedexp_mantissabits))) + 0.5f));
57 0 : output.G = static_cast<unsigned int>(floor((green_c / (pow(2.0f, exp_s - g_sharedexp_bias - g_sharedexp_mantissabits))) + 0.5f));
58 0 : output.B = static_cast<unsigned int>(floor((blue_c / (pow(2.0f, exp_s - g_sharedexp_bias - g_sharedexp_mantissabits))) + 0.5f));
59 0 : output.E = exp_s;
60 :
61 0 : return bitCast<unsigned int>(output);
62 : }
63 :
64 0 : void convert999E5toRGBFloats(unsigned int input, float *red, float *green, float *blue)
65 : {
66 0 : const RGB9E5Data *inputData = reinterpret_cast<const RGB9E5Data*>(&input);
67 :
68 0 : *red = inputData->R * pow(2.0f, (int)inputData->E - g_sharedexp_bias - g_sharedexp_mantissabits);
69 0 : *green = inputData->G * pow(2.0f, (int)inputData->E - g_sharedexp_bias - g_sharedexp_mantissabits);
70 0 : *blue = inputData->B * pow(2.0f, (int)inputData->E - g_sharedexp_bias - g_sharedexp_mantissabits);
71 0 : }
72 :
73 : } // namespace gl
|