blob: 927b6ebebe27657b78016101352e5c9754b72221 [file] [log] [blame]
shannonwoods@chromium.org92b9cd52013-05-30 00:14:48 +00001//
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"
Geoff Lang0b7eef72014-06-12 14:10:47 -040010
Geoff Lang17732822013-08-29 13:46:49 -040011#include <algorithm>
Jamie Madill4f267862014-04-17 15:53:37 -040012#include <math.h>
shannonwoods@chromium.org92b9cd52013-05-30 00:14:48 +000013
14namespace gl
15{
16
17struct RGB9E5Data
18{
19 unsigned int R : 9;
20 unsigned int G : 9;
21 unsigned int B : 9;
22 unsigned int E : 5;
23};
24
25// B is the exponent bias (15)
26static const int g_sharedexp_bias = 15;
27
28// N is the number of mantissa bits per component (9)
29static const int g_sharedexp_mantissabits = 9;
30
31// Emax is the maximum allowed biased exponent value (31)
32static const int g_sharedexp_maxexponent = 31;
33
34static const float g_sharedexp_max = ((pow(2.0f, g_sharedexp_mantissabits) - 1) /
35 pow(2.0f, g_sharedexp_mantissabits)) *
36 pow(2.0f, g_sharedexp_maxexponent - g_sharedexp_bias);
37
38unsigned int convertRGBFloatsTo999E5(float red, float green, float blue)
39{
40 const float red_c = std::max<float>(0, std::min(g_sharedexp_max, red));
41 const float green_c = std::max<float>(0, std::min(g_sharedexp_max, green));
42 const float blue_c = std::max<float>(0, std::min(g_sharedexp_max, blue));
43
44 const float max_c = std::max<float>(std::max<float>(red_c, green_c), blue_c);
45 const float exp_p = std::max<float>(-g_sharedexp_bias - 1, floor(log(max_c))) + 1 + g_sharedexp_bias;
Minmin Gong794e0002015-04-07 18:31:54 -070046 const int max_s = static_cast<int>(floor((max_c / (pow(2.0f, exp_p - g_sharedexp_bias - g_sharedexp_mantissabits))) + 0.5f));
47 const int exp_s = static_cast<int>((max_s < pow(2.0f, g_sharedexp_mantissabits)) ? exp_p : exp_p + 1);
shannonwoods@chromium.org92b9cd52013-05-30 00:14:48 +000048
49 RGB9E5Data output;
Minmin Gong794e0002015-04-07 18:31:54 -070050 output.R = static_cast<unsigned int>(floor((red_c / (pow(2.0f, exp_s - g_sharedexp_bias - g_sharedexp_mantissabits))) + 0.5f));
51 output.G = static_cast<unsigned int>(floor((green_c / (pow(2.0f, exp_s - g_sharedexp_bias - g_sharedexp_mantissabits))) + 0.5f));
52 output.B = static_cast<unsigned int>(floor((blue_c / (pow(2.0f, exp_s - g_sharedexp_bias - g_sharedexp_mantissabits))) + 0.5f));
shannonwoods@chromium.org92b9cd52013-05-30 00:14:48 +000053 output.E = exp_s;
54
hendrikw75782622015-09-25 11:28:50 -070055 return bitCast<unsigned int>(output);
shannonwoods@chromium.org92b9cd52013-05-30 00:14:48 +000056}
57
58void convert999E5toRGBFloats(unsigned int input, float *red, float *green, float *blue)
59{
60 const RGB9E5Data *inputData = reinterpret_cast<const RGB9E5Data*>(&input);
61
62 *red = inputData->R * pow(2.0f, (int)inputData->E - g_sharedexp_bias - g_sharedexp_mantissabits);
63 *green = inputData->G * pow(2.0f, (int)inputData->E - g_sharedexp_bias - g_sharedexp_mantissabits);
64 *blue = inputData->B * pow(2.0f, (int)inputData->E - g_sharedexp_bias - g_sharedexp_mantissabits);
65}
66
67}