1f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/* 2f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Copyright (C) 2011 Marek Olšák <maraeo@gmail.com> 3f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 4f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Permission is hereby granted, free of charge, to any person obtaining a 5f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * copy of this software and associated documentation files (the "Software"), 6f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * to deal in the Software without restriction, including without limitation 7f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * and/or sell copies of the Software, and to permit persons to whom the 9f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Software is furnished to do so, subject to the following conditions: 10f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 11f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * The above copyright notice and this permission notice (including the next 12f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * paragraph) shall be included in all copies or substantial portions of the 13f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Software. 14f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 15f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * DEALINGS IN THE SOFTWARE. 22f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 23f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 24f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/* Copied from EXT_texture_shared_exponent and edited. */ 25f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 26f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#ifndef RGB9E5_H 27f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define RGB9E5_H 28f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 29f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include <math.h> 30f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include <assert.h> 31f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 32f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define RGB9E5_EXPONENT_BITS 5 33f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define RGB9E5_MANTISSA_BITS 9 34f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define RGB9E5_EXP_BIAS 15 35f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define RGB9E5_MAX_VALID_BIASED_EXP 31 36f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 37f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define MAX_RGB9E5_EXP (RGB9E5_MAX_VALID_BIASED_EXP - RGB9E5_EXP_BIAS) 38f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define RGB9E5_MANTISSA_VALUES (1<<RGB9E5_MANTISSA_BITS) 39f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define MAX_RGB9E5_MANTISSA (RGB9E5_MANTISSA_VALUES-1) 40f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define MAX_RGB9E5 (((float)MAX_RGB9E5_MANTISSA)/RGB9E5_MANTISSA_VALUES * (1<<MAX_RGB9E5_EXP)) 41f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define EPSILON_RGB9E5 ((1.0/RGB9E5_MANTISSA_VALUES) / (1<<RGB9E5_EXP_BIAS)) 42f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 43f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgtypedef union { 44f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org unsigned int raw; 45f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org float value; 46f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org struct { 47f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#if defined(MESA_BIG_ENDIAN) || defined(PIPE_ARCH_BIG_ENDIAN) 48f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org unsigned int negative:1; 49f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org unsigned int biasedexponent:8; 50f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org unsigned int mantissa:23; 51f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#else 52f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org unsigned int mantissa:23; 53f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org unsigned int biasedexponent:8; 54f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org unsigned int negative:1; 55f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif 56f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } field; 57f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} float754; 58f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 59f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgtypedef union { 60f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org unsigned int raw; 61f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org struct { 62f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#if defined(MESA_BIG_ENDIAN) || defined(PIPE_ARCH_BIG_ENDIAN) 63f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org unsigned int biasedexponent:RGB9E5_EXPONENT_BITS; 64f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org unsigned int b:RGB9E5_MANTISSA_BITS; 65f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org unsigned int g:RGB9E5_MANTISSA_BITS; 66f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org unsigned int r:RGB9E5_MANTISSA_BITS; 67f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#else 68f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org unsigned int r:RGB9E5_MANTISSA_BITS; 69f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org unsigned int g:RGB9E5_MANTISSA_BITS; 70f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org unsigned int b:RGB9E5_MANTISSA_BITS; 71f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org unsigned int biasedexponent:RGB9E5_EXPONENT_BITS; 72f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif 73f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } field; 74f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} rgb9e5; 75f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 76f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic INLINE float rgb9e5_ClampRange(float x) 77f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{ 78f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (x > 0.0) { 79f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (x >= MAX_RGB9E5) { 80f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return MAX_RGB9E5; 81f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } else { 82f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return x; 83f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 84f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } else { 85f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* NaN gets here too since comparisons with NaN always fail! */ 86f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return 0.0; 87f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 88f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 89f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 90f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/* Ok, FloorLog2 is not correct for the denorm and zero values, but we 91f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org are going to do a max of this value with the minimum rgb9e5 exponent 92f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org that will hide these problem cases. */ 93f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic INLINE int rgb9e5_FloorLog2(float x) 94f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{ 95f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org float754 f; 96f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 97f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org f.value = x; 98f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return (f.field.biasedexponent - 127); 99f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 100f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 101f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic INLINE unsigned float3_to_rgb9e5(const float rgb[3]) 102f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{ 103f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org rgb9e5 retval; 104f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org float maxrgb; 105f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org int rm, gm, bm; 106f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org float rc, gc, bc; 107f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org int exp_shared, maxm; 108f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org double denom; 109f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 110f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org rc = rgb9e5_ClampRange(rgb[0]); 111f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org gc = rgb9e5_ClampRange(rgb[1]); 112f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org bc = rgb9e5_ClampRange(rgb[2]); 113f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 114f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org maxrgb = MAX3(rc, gc, bc); 115f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org exp_shared = MAX2(-RGB9E5_EXP_BIAS-1, rgb9e5_FloorLog2(maxrgb)) + 1 + RGB9E5_EXP_BIAS; 116f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org assert(exp_shared <= RGB9E5_MAX_VALID_BIASED_EXP); 117f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org assert(exp_shared >= 0); 118f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* This pow function could be replaced by a table. */ 119f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org denom = pow(2, exp_shared - RGB9E5_EXP_BIAS - RGB9E5_MANTISSA_BITS); 120f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 121f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org maxm = (int) floor(maxrgb / denom + 0.5); 122f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (maxm == MAX_RGB9E5_MANTISSA+1) { 123f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org denom *= 2; 124f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org exp_shared += 1; 125f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org assert(exp_shared <= RGB9E5_MAX_VALID_BIASED_EXP); 126f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } else { 127f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org assert(maxm <= MAX_RGB9E5_MANTISSA); 128f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 129f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 130f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org rm = (int) floor(rc / denom + 0.5); 131f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org gm = (int) floor(gc / denom + 0.5); 132f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org bm = (int) floor(bc / denom + 0.5); 133f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 134f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org assert(rm <= MAX_RGB9E5_MANTISSA); 135f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org assert(gm <= MAX_RGB9E5_MANTISSA); 136f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org assert(bm <= MAX_RGB9E5_MANTISSA); 137f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org assert(rm >= 0); 138f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org assert(gm >= 0); 139f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org assert(bm >= 0); 140f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 141f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org retval.field.r = rm; 142f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org retval.field.g = gm; 143f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org retval.field.b = bm; 144f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org retval.field.biasedexponent = exp_shared; 145f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 146f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return retval.raw; 147f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 148f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 149f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic INLINE void rgb9e5_to_float3(unsigned rgb, float retval[3]) 150f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{ 151f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org rgb9e5 v; 152f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org int exponent; 153f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org float scale; 154f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 155f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org v.raw = rgb; 156f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org exponent = v.field.biasedexponent - RGB9E5_EXP_BIAS - RGB9E5_MANTISSA_BITS; 157f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org scale = (float) pow(2, exponent); 158f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 159f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org retval[0] = v.field.r * scale; 160f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org retval[1] = v.field.g * scale; 161f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org retval[2] = v.field.b * scale; 162f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 163f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 164f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif 165