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 struct 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) 26 static const int g_sharedexp_bias = 15; 27 28 // N is the number of mantissa bits per component (9) 29 static const int g_sharedexp_mantissabits = 9; 30 31 // Emax is the maximum allowed biased exponent value (31) 32 static const int g_sharedexp_maxexponent = 31; 33 34 static 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 38 unsigned 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; 46 const int max_s = floor((max_c / (pow(2.0f, exp_p - g_sharedexp_bias - g_sharedexp_mantissabits))) + 0.5f); 47 const int exp_s = (max_s < pow(2.0f, g_sharedexp_mantissabits)) ? exp_p : exp_p + 1; 48 49 RGB9E5Data output; 50 output.R = floor((red_c / (pow(2.0f, exp_s - g_sharedexp_bias - g_sharedexp_mantissabits))) + 0.5f); 51 output.G = floor((green_c / (pow(2.0f, exp_s - g_sharedexp_bias - g_sharedexp_mantissabits))) + 0.5f); 52 output.B = floor((blue_c / (pow(2.0f, exp_s - g_sharedexp_bias - g_sharedexp_mantissabits))) + 0.5f); 53 output.E = exp_s; 54 55 return *reinterpret_cast<unsigned int*>(&output); 56 } 57 58 void 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 } 68