19d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák/* 29d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák * Copyright (C) 2011 Marek Olšák <maraeo@gmail.com> 39d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák * 49d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák * Permission is hereby granted, free of charge, to any person obtaining a 59d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák * copy of this software and associated documentation files (the "Software"), 69d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák * to deal in the Software without restriction, including without limitation 79d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák * the rights to use, copy, modify, merge, publish, distribute, sublicense, 89d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák * and/or sell copies of the Software, and to permit persons to whom the 99d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák * Software is furnished to do so, subject to the following conditions: 109d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák * 119d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák * The above copyright notice and this permission notice (including the next 129d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák * paragraph) shall be included in all copies or substantial portions of the 139d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák * Software. 149d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák * 159d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 169d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 179d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 189d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 199d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 209d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 219d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák * DEALINGS IN THE SOFTWARE. 229d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák */ 239d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák 249d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák/* Copied from EXT_texture_shared_exponent and edited. */ 259d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák 269d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák#ifndef RGB9E5_H 279d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák#define RGB9E5_H 289d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák 299d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák#include <math.h> 309d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák#include <assert.h> 319d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák 329d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák#define RGB9E5_EXPONENT_BITS 5 339d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák#define RGB9E5_MANTISSA_BITS 9 349d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák#define RGB9E5_EXP_BIAS 15 359d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák#define RGB9E5_MAX_VALID_BIASED_EXP 31 369d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák 379d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák#define MAX_RGB9E5_EXP (RGB9E5_MAX_VALID_BIASED_EXP - RGB9E5_EXP_BIAS) 389d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák#define RGB9E5_MANTISSA_VALUES (1<<RGB9E5_MANTISSA_BITS) 399d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák#define MAX_RGB9E5_MANTISSA (RGB9E5_MANTISSA_VALUES-1) 409d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák#define MAX_RGB9E5 (((float)MAX_RGB9E5_MANTISSA)/RGB9E5_MANTISSA_VALUES * (1<<MAX_RGB9E5_EXP)) 419d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák#define EPSILON_RGB9E5 ((1.0/RGB9E5_MANTISSA_VALUES) / (1<<RGB9E5_EXP_BIAS)) 429d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák 439d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšáktypedef union { 449d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák unsigned int raw; 459d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák float value; 469d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák struct { 479d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák#if defined(MESA_BIG_ENDIAN) || defined(PIPE_ARCH_BIG_ENDIAN) 489d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák unsigned int negative:1; 499d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák unsigned int biasedexponent:8; 509d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák unsigned int mantissa:23; 519d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák#else 529d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák unsigned int mantissa:23; 539d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák unsigned int biasedexponent:8; 549d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák unsigned int negative:1; 559d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák#endif 569d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák } field; 579d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák} float754; 589d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák 599d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšáktypedef union { 609d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák unsigned int raw; 619d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák struct { 629d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák#if defined(MESA_BIG_ENDIAN) || defined(PIPE_ARCH_BIG_ENDIAN) 639d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák unsigned int biasedexponent:RGB9E5_EXPONENT_BITS; 649d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák unsigned int b:RGB9E5_MANTISSA_BITS; 659d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák unsigned int g:RGB9E5_MANTISSA_BITS; 669d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák unsigned int r:RGB9E5_MANTISSA_BITS; 679d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák#else 689d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák unsigned int r:RGB9E5_MANTISSA_BITS; 699d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák unsigned int g:RGB9E5_MANTISSA_BITS; 709d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák unsigned int b:RGB9E5_MANTISSA_BITS; 719d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák unsigned int biasedexponent:RGB9E5_EXPONENT_BITS; 729d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák#endif 739d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák } field; 749d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák} rgb9e5; 759d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák 769d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšákstatic INLINE float rgb9e5_ClampRange(float x) 779d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák{ 789d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák if (x > 0.0) { 799d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák if (x >= MAX_RGB9E5) { 809d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák return MAX_RGB9E5; 819d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák } else { 829d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák return x; 839d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák } 849d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák } else { 859d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák /* NaN gets here too since comparisons with NaN always fail! */ 869d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák return 0.0; 879d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák } 889d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák} 899d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák 909d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák/* Ok, FloorLog2 is not correct for the denorm and zero values, but we 919d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák are going to do a max of this value with the minimum rgb9e5 exponent 929d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák that will hide these problem cases. */ 939d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšákstatic INLINE int rgb9e5_FloorLog2(float x) 949d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák{ 959d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák float754 f; 969d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák 979d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák f.value = x; 989d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák return (f.field.biasedexponent - 127); 999d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák} 1009d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák 1019d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšákstatic INLINE unsigned float3_to_rgb9e5(const float rgb[3]) 1029d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák{ 1039d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák rgb9e5 retval; 1049d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák float maxrgb; 1059d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák int rm, gm, bm; 1069d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák float rc, gc, bc; 1079d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák int exp_shared, maxm; 1089d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák double denom; 1099d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák 1109d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák rc = rgb9e5_ClampRange(rgb[0]); 1119d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák gc = rgb9e5_ClampRange(rgb[1]); 1129d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák bc = rgb9e5_ClampRange(rgb[2]); 1139d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák 1141271424615b62544662a606bb23f6d7117a8b0e7Marek Olšák maxrgb = MAX3(rc, gc, bc); 1159d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák exp_shared = MAX2(-RGB9E5_EXP_BIAS-1, rgb9e5_FloorLog2(maxrgb)) + 1 + RGB9E5_EXP_BIAS; 1169d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák assert(exp_shared <= RGB9E5_MAX_VALID_BIASED_EXP); 1179d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák assert(exp_shared >= 0); 1189d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák /* This pow function could be replaced by a table. */ 1199d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák denom = pow(2, exp_shared - RGB9E5_EXP_BIAS - RGB9E5_MANTISSA_BITS); 1209d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák 1219d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák maxm = (int) floor(maxrgb / denom + 0.5); 1229d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák if (maxm == MAX_RGB9E5_MANTISSA+1) { 1239d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák denom *= 2; 1249d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák exp_shared += 1; 1259d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák assert(exp_shared <= RGB9E5_MAX_VALID_BIASED_EXP); 1269d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák } else { 1279d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák assert(maxm <= MAX_RGB9E5_MANTISSA); 1289d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák } 1299d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák 1309d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák rm = (int) floor(rc / denom + 0.5); 1319d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák gm = (int) floor(gc / denom + 0.5); 1329d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák bm = (int) floor(bc / denom + 0.5); 1339d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák 1349d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák assert(rm <= MAX_RGB9E5_MANTISSA); 1359d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák assert(gm <= MAX_RGB9E5_MANTISSA); 1369d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák assert(bm <= MAX_RGB9E5_MANTISSA); 1379d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák assert(rm >= 0); 1389d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák assert(gm >= 0); 1399d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák assert(bm >= 0); 1409d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák 1419d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák retval.field.r = rm; 1429d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák retval.field.g = gm; 1439d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák retval.field.b = bm; 1449d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák retval.field.biasedexponent = exp_shared; 1459d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák 1469d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák return retval.raw; 1479d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák} 1489d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák 1499d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšákstatic INLINE void rgb9e5_to_float3(unsigned rgb, float retval[3]) 1509d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák{ 1519d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák rgb9e5 v; 1529d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák int exponent; 1539d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák float scale; 1549d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák 1559d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák v.raw = rgb; 1569d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák exponent = v.field.biasedexponent - RGB9E5_EXP_BIAS - RGB9E5_MANTISSA_BITS; 1579d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák scale = (float) pow(2, exponent); 1589d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák 1599d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák retval[0] = v.field.r * scale; 1609d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák retval[1] = v.field.g * scale; 1619d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák retval[2] = v.field.b * scale; 1629d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák} 1639d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák 1649d7698c468f4ea7da8bb4ec00520c98f11cca0faMarek Olšák#endif 165