Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

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