mathutil.cpp (2721B)
1 // 2 // Copyright 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 <math.h> 12 #include <algorithm> 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 // number of mantissa bits per component pre-biased 35 constexpr int g_sharedexp_biased_mantissabits = g_sharedexp_bias + g_sharedexp_mantissabits; 36 37 // Emax is the maximum allowed biased exponent value (31) 38 constexpr int g_sharedexp_maxexponent = 31; 39 40 constexpr float g_sharedexp_max = 41 ((static_cast<float>(1 << g_sharedexp_mantissabits) - 1) / 42 static_cast<float>(1 << g_sharedexp_mantissabits)) * 43 static_cast<float>(1 << (g_sharedexp_maxexponent - g_sharedexp_bias)); 44 45 } // anonymous namespace 46 47 unsigned int convertRGBFloatsTo999E5(float red, float green, float blue) 48 { 49 const float red_c = std::max<float>(0, std::min(g_sharedexp_max, red)); 50 const float green_c = std::max<float>(0, std::min(g_sharedexp_max, green)); 51 const float blue_c = std::max<float>(0, std::min(g_sharedexp_max, blue)); 52 53 const float max_c = std::max<float>(std::max<float>(red_c, green_c), blue_c); 54 const float exp_p = 55 std::max<float>(-g_sharedexp_bias - 1, floor(log(max_c))) + 1 + g_sharedexp_bias; 56 const int max_s = static_cast<int>( 57 floor((max_c / (pow(2.0f, exp_p - g_sharedexp_biased_mantissabits))) + 0.5f)); 58 const int exp_s = 59 static_cast<int>((max_s < pow(2.0f, g_sharedexp_mantissabits)) ? exp_p : exp_p + 1); 60 const float pow2_exp = pow(2.0f, static_cast<float>(exp_s) - g_sharedexp_biased_mantissabits); 61 62 RGB9E5Data output; 63 output.R = static_cast<unsigned int>(floor((red_c / pow2_exp) + 0.5f)); 64 output.G = static_cast<unsigned int>(floor((green_c / pow2_exp) + 0.5f)); 65 output.B = static_cast<unsigned int>(floor((blue_c / pow2_exp) + 0.5f)); 66 output.E = exp_s; 67 68 return bitCast<unsigned int>(output); 69 } 70 71 void convert999E5toRGBFloats(unsigned int input, float *red, float *green, float *blue) 72 { 73 const RGB9E5Data *inputData = reinterpret_cast<const RGB9E5Data *>(&input); 74 75 const float pow2_exp = 76 pow(2.0f, static_cast<float>(inputData->E) - g_sharedexp_biased_mantissabits); 77 78 *red = inputData->R * pow2_exp; 79 *green = inputData->G * pow2_exp; 80 *blue = inputData->B * pow2_exp; 81 } 82 83 } // namespace gl