| [7908] | 1 | /* | 
|---|
 | 2 | ----------------------------------------------------------------------------- | 
|---|
 | 3 | This source file is part of OGRE | 
|---|
 | 4 |     (Object-oriented Graphics Rendering Engine) | 
|---|
 | 5 | For the latest info, see http://www.ogre3d.org/ | 
|---|
 | 6 |  | 
|---|
 | 7 | Copyright (c) 2000-2006 Torus Knot Software Ltd | 
|---|
 | 8 | Also see acknowledgements in Readme.html | 
|---|
 | 9 |  | 
|---|
 | 10 | This program is free software; you can redistribute it and/or modify it under | 
|---|
 | 11 | the terms of the GNU Lesser General Public License as published by the Free Software | 
|---|
 | 12 | Foundation; either version 2 of the License, or (at your option) any later | 
|---|
 | 13 | version. | 
|---|
 | 14 |  | 
|---|
 | 15 | This program is distributed in the hope that it will be useful, but WITHOUT | 
|---|
 | 16 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS | 
|---|
 | 17 | FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. | 
|---|
 | 18 |  | 
|---|
 | 19 | You should have received a copy of the GNU Lesser General Public License along with | 
|---|
 | 20 | this program; if not, write to the Free Software Foundation, Inc., 59 Temple | 
|---|
 | 21 | Place - Suite 330, Boston, MA 02111-1307, USA, or go to | 
|---|
 | 22 | http://www.gnu.org/copyleft/lesser.txt. | 
|---|
 | 23 |  | 
|---|
 | 24 | You may alternatively use this source under the terms of a specific version of | 
|---|
 | 25 | the OGRE Unrestricted License provided you have obtained such a license from | 
|---|
 | 26 | Torus Knot Software Ltd. | 
|---|
 | 27 | ----------------------------------------------------------------------------- | 
|---|
 | 28 | */ | 
|---|
 | 29 | #ifndef _Bitwise_H__ | 
|---|
 | 30 | #define _Bitwise_H__ | 
|---|
 | 31 |  | 
|---|
 | 32 | #include "OgrePrerequisites.h" | 
|---|
 | 33 |  | 
|---|
 | 34 | namespace Ogre { | 
|---|
 | 35 |  | 
|---|
 | 36 |     /** Class for manipulating bit patterns. | 
|---|
 | 37 |     */ | 
|---|
 | 38 |     class Bitwise { | 
|---|
 | 39 |     public: | 
|---|
 | 40 |         /** Returns the most significant bit set in a value. | 
|---|
 | 41 |         */ | 
|---|
 | 42 |         static FORCEINLINE unsigned int mostSignificantBitSet(unsigned int value) | 
|---|
 | 43 |         { | 
|---|
 | 44 |             unsigned int result = 0; | 
|---|
 | 45 |             while (value != 0) { | 
|---|
 | 46 |                 ++result; | 
|---|
 | 47 |                 value >>= 1; | 
|---|
 | 48 |             } | 
|---|
 | 49 |             return result-1; | 
|---|
 | 50 |         } | 
|---|
 | 51 |         /** Returns the closest power-of-two number greater or equal to value. | 
|---|
 | 52 |             @note 0 and 1 are powers of two, so  | 
|---|
 | 53 |                 firstPO2From(0)==0 and firstPO2From(1)==1. | 
|---|
 | 54 |         */ | 
|---|
 | 55 |         static FORCEINLINE uint32 firstPO2From(uint32 n) | 
|---|
 | 56 |         { | 
|---|
 | 57 |             --n;             | 
|---|
 | 58 |             n |= n >> 16; | 
|---|
 | 59 |             n |= n >> 8; | 
|---|
 | 60 |             n |= n >> 4; | 
|---|
 | 61 |             n |= n >> 2; | 
|---|
 | 62 |             n |= n >> 1; | 
|---|
 | 63 |             ++n; | 
|---|
 | 64 |             return n; | 
|---|
 | 65 |         } | 
|---|
 | 66 |         /** Determines whether the number is power-of-two or not. | 
|---|
 | 67 |             @note 0 and 1 are tread as power of two. | 
|---|
 | 68 |         */ | 
|---|
 | 69 |         template<typename T> | 
|---|
 | 70 |         static FORCEINLINE bool isPO2(T n) | 
|---|
 | 71 |         { | 
|---|
 | 72 |             return (n & (n-1)) == 0; | 
|---|
 | 73 |         } | 
|---|
 | 74 |         /** Returns the number of bits a pattern must be shifted right by to | 
|---|
 | 75 |             remove right-hand zeros. | 
|---|
 | 76 |         */ | 
|---|
 | 77 |                 template<typename T> | 
|---|
 | 78 |         static FORCEINLINE unsigned int getBitShift(T mask) | 
|---|
 | 79 |                 { | 
|---|
 | 80 |                         if (mask == 0) | 
|---|
 | 81 |                                 return 0; | 
|---|
 | 82 |  | 
|---|
 | 83 |                         unsigned int result = 0; | 
|---|
 | 84 |                         while ((mask & 1) == 0) { | 
|---|
 | 85 |                                 ++result; | 
|---|
 | 86 |                                 mask >>= 1; | 
|---|
 | 87 |                         } | 
|---|
 | 88 |                         return result; | 
|---|
 | 89 |                 } | 
|---|
 | 90 |  | 
|---|
 | 91 |         /** Takes a value with a given src bit mask, and produces another | 
|---|
 | 92 |             value with a desired bit mask. | 
|---|
 | 93 |             @remarks | 
|---|
 | 94 |                 This routine is useful for colour conversion. | 
|---|
 | 95 |         */ | 
|---|
 | 96 |                 template<typename SrcT, typename DestT> | 
|---|
 | 97 |         static inline DestT convertBitPattern(SrcT srcValue, SrcT srcBitMask, DestT destBitMask) | 
|---|
 | 98 |                 { | 
|---|
 | 99 |                         // Mask off irrelevant source value bits (if any) | 
|---|
 | 100 |                         srcValue = srcValue & srcBitMask; | 
|---|
 | 101 |  | 
|---|
 | 102 |                         // Shift source down to bottom of DWORD | 
|---|
 | 103 |                         const unsigned int srcBitShift = getBitShift(srcBitMask); | 
|---|
 | 104 |                         srcValue >>= srcBitShift; | 
|---|
 | 105 |  | 
|---|
 | 106 |                         // Get max value possible in source from srcMask | 
|---|
 | 107 |                         const SrcT srcMax = srcBitMask >> srcBitShift; | 
|---|
 | 108 |  | 
|---|
 | 109 |                         // Get max available in dest | 
|---|
 | 110 |                         const unsigned int destBitShift = getBitShift(destBitMask); | 
|---|
 | 111 |                         const DestT destMax = destBitMask >> destBitShift; | 
|---|
 | 112 |  | 
|---|
 | 113 |                         // Scale source value into destination, and shift back | 
|---|
 | 114 |                         DestT destValue = (srcValue * destMax) / srcMax; | 
|---|
 | 115 |                         return (destValue << destBitShift); | 
|---|
 | 116 |                 } | 
|---|
 | 117 |  | 
|---|
 | 118 |         /** | 
|---|
 | 119 |          * Convert N bit colour channel value to P bits. It fills P bits with the | 
|---|
 | 120 |          * bit pattern repeated. (this is /((1<<n)-1) in fixed point) | 
|---|
 | 121 |          */ | 
|---|
 | 122 |         static inline unsigned int fixedToFixed(uint32 value, unsigned int n, unsigned int p)  | 
|---|
 | 123 |         { | 
|---|
 | 124 |             if(n > p)  | 
|---|
 | 125 |             { | 
|---|
 | 126 |                 // Less bits required than available; this is easy | 
|---|
 | 127 |                 value >>= n-p; | 
|---|
 | 128 |             }  | 
|---|
 | 129 |             else if(n < p) | 
|---|
 | 130 |             { | 
|---|
 | 131 |                 // More bits required than are there, do the fill | 
|---|
 | 132 |                 // Use old fashioned division, probably better than a loop | 
|---|
 | 133 |                 if(value == 0) | 
|---|
 | 134 |                         value = 0; | 
|---|
 | 135 |                 else if(value == (static_cast<unsigned int>(1)<<n)-1) | 
|---|
 | 136 |                         value = (1<<p)-1; | 
|---|
 | 137 |                 else    value = value*(1<<p)/((1<<n)-1); | 
|---|
 | 138 |             } | 
|---|
 | 139 |             return value;     | 
|---|
 | 140 |         } | 
|---|
 | 141 |  | 
|---|
 | 142 |         /** | 
|---|
 | 143 |          * Convert floating point colour channel value between 0.0 and 1.0 (otherwise clamped)  | 
|---|
 | 144 |          * to integer of a certain number of bits. Works for any value of bits between 0 and 31. | 
|---|
 | 145 |          */ | 
|---|
 | 146 |         static inline unsigned int floatToFixed(const float value, const unsigned int bits) | 
|---|
 | 147 |         { | 
|---|
 | 148 |             if(value <= 0.0f) return 0; | 
|---|
 | 149 |             else if (value >= 1.0f) return (1<<bits)-1; | 
|---|
 | 150 |             else return (unsigned int)(value * (1<<bits));      | 
|---|
 | 151 |         } | 
|---|
 | 152 |  | 
|---|
 | 153 |         /** | 
|---|
 | 154 |          * Fixed point to float | 
|---|
 | 155 |          */ | 
|---|
 | 156 |         static inline float fixedToFloat(unsigned value, unsigned int bits) | 
|---|
 | 157 |         { | 
|---|
 | 158 |             return (float)value/(float)((1<<bits)-1); | 
|---|
 | 159 |         } | 
|---|
 | 160 |  | 
|---|
 | 161 |         /** | 
|---|
 | 162 |          * Write a n*8 bits integer value to memory in native endian. | 
|---|
 | 163 |          */ | 
|---|
 | 164 |         static inline void intWrite(void *dest, const int n, const unsigned int value) | 
|---|
 | 165 |         { | 
|---|
 | 166 |             switch(n) { | 
|---|
 | 167 |                 case 1: | 
|---|
 | 168 |                     ((uint8*)dest)[0] = (uint8)value; | 
|---|
 | 169 |                     break; | 
|---|
 | 170 |                 case 2: | 
|---|
 | 171 |                     ((uint16*)dest)[0] = (uint16)value; | 
|---|
 | 172 |                     break; | 
|---|
 | 173 |                 case 3: | 
|---|
 | 174 | #if OGRE_ENDIAN == OGRE_ENDIAN_BIG       | 
|---|
 | 175 |                     ((uint8*)dest)[0] = (uint8)((value >> 16) & 0xFF); | 
|---|
 | 176 |                     ((uint8*)dest)[1] = (uint8)((value >> 8) & 0xFF); | 
|---|
 | 177 |                     ((uint8*)dest)[2] = (uint8)(value & 0xFF); | 
|---|
 | 178 | #else | 
|---|
 | 179 |                     ((uint8*)dest)[2] = (uint8)((value >> 16) & 0xFF); | 
|---|
 | 180 |                     ((uint8*)dest)[1] = (uint8)((value >> 8) & 0xFF); | 
|---|
 | 181 |                     ((uint8*)dest)[0] = (uint8)(value & 0xFF); | 
|---|
 | 182 | #endif | 
|---|
 | 183 |                     break; | 
|---|
 | 184 |                 case 4: | 
|---|
 | 185 |                     ((uint32*)dest)[0] = (uint32)value;                 | 
|---|
 | 186 |                     break;                 | 
|---|
 | 187 |             }         | 
|---|
 | 188 |         } | 
|---|
 | 189 |         /** | 
|---|
 | 190 |          * Read a n*8 bits integer value to memory in native endian. | 
|---|
 | 191 |          */ | 
|---|
 | 192 |         static inline unsigned int intRead(const void *src, int n) { | 
|---|
 | 193 |             switch(n) { | 
|---|
 | 194 |                 case 1: | 
|---|
 | 195 |                     return ((uint8*)src)[0]; | 
|---|
 | 196 |                 case 2: | 
|---|
 | 197 |                     return ((uint16*)src)[0]; | 
|---|
 | 198 |                 case 3: | 
|---|
 | 199 | #if OGRE_ENDIAN == OGRE_ENDIAN_BIG       | 
|---|
 | 200 |                     return ((uint32)((uint8*)src)[0]<<16)| | 
|---|
 | 201 |                             ((uint32)((uint8*)src)[1]<<8)| | 
|---|
 | 202 |                             ((uint32)((uint8*)src)[2]); | 
|---|
 | 203 | #else | 
|---|
 | 204 |                     return ((uint32)((uint8*)src)[0])| | 
|---|
 | 205 |                             ((uint32)((uint8*)src)[1]<<8)| | 
|---|
 | 206 |                             ((uint32)((uint8*)src)[2]<<16); | 
|---|
 | 207 | #endif | 
|---|
 | 208 |                 case 4: | 
|---|
 | 209 |                     return ((uint32*)src)[0]; | 
|---|
 | 210 |             }  | 
|---|
 | 211 |             return 0; // ? | 
|---|
 | 212 |         } | 
|---|
 | 213 |  | 
|---|
 | 214 |         /** Convert a float32 to a float16 (NV_half_float) | 
|---|
 | 215 |                 Courtesy of OpenEXR | 
|---|
 | 216 |         */ | 
|---|
 | 217 |         static inline uint16 floatToHalf(float i) | 
|---|
 | 218 |         { | 
|---|
 | 219 |             union { float f; uint32 i; } v; | 
|---|
 | 220 |             v.f = i; | 
|---|
 | 221 |             return floatToHalfI(v.i); | 
|---|
 | 222 |         } | 
|---|
 | 223 |                 /** Converts float in uint32 format to a a half in uint16 format | 
|---|
 | 224 |                 */ | 
|---|
 | 225 |         static inline uint16 floatToHalfI(uint32 i) | 
|---|
 | 226 |         { | 
|---|
 | 227 |             register int s =  (i >> 16) & 0x00008000; | 
|---|
 | 228 |             register int e = ((i >> 23) & 0x000000ff) - (127 - 15); | 
|---|
 | 229 |             register int m =   i        & 0x007fffff; | 
|---|
 | 230 |          | 
|---|
 | 231 |             if (e <= 0) | 
|---|
 | 232 |             { | 
|---|
 | 233 |                 if (e < -10) | 
|---|
 | 234 |                 { | 
|---|
 | 235 |                     return 0; | 
|---|
 | 236 |                 } | 
|---|
 | 237 |                 m = (m | 0x00800000) >> (1 - e); | 
|---|
 | 238 |          | 
|---|
 | 239 |                 return s | (m >> 13); | 
|---|
 | 240 |             } | 
|---|
 | 241 |             else if (e == 0xff - (127 - 15)) | 
|---|
 | 242 |             { | 
|---|
 | 243 |                 if (m == 0) // Inf | 
|---|
 | 244 |                 { | 
|---|
 | 245 |                     return s | 0x7c00; | 
|---|
 | 246 |                 }  | 
|---|
 | 247 |                 else    // NAN | 
|---|
 | 248 |                 { | 
|---|
 | 249 |                     m >>= 13; | 
|---|
 | 250 |                     return s | 0x7c00 | m | (m == 0); | 
|---|
 | 251 |                 } | 
|---|
 | 252 |             } | 
|---|
 | 253 |             else | 
|---|
 | 254 |             { | 
|---|
 | 255 |                 if (e > 30) // Overflow | 
|---|
 | 256 |                 { | 
|---|
 | 257 |                     return s | 0x7c00; | 
|---|
 | 258 |                 } | 
|---|
 | 259 |          | 
|---|
 | 260 |                 return s | (e << 10) | (m >> 13); | 
|---|
 | 261 |             } | 
|---|
 | 262 |         } | 
|---|
 | 263 |          | 
|---|
 | 264 |         /** | 
|---|
 | 265 |          * Convert a float16 (NV_half_float) to a float32 | 
|---|
 | 266 |          * Courtesy of OpenEXR | 
|---|
 | 267 |          */ | 
|---|
 | 268 |         static inline float halfToFloat(uint16 y) | 
|---|
 | 269 |         { | 
|---|
 | 270 |             union { float f; uint32 i; } v; | 
|---|
 | 271 |             v.i = halfToFloatI(y); | 
|---|
 | 272 |             return v.f; | 
|---|
 | 273 |         } | 
|---|
 | 274 |                 /** Converts a half in uint16 format to a float | 
|---|
 | 275 |                         in uint32 format | 
|---|
 | 276 |                  */ | 
|---|
 | 277 |         static inline uint32 halfToFloatI(uint16 y) | 
|---|
 | 278 |         { | 
|---|
 | 279 |             register int s = (y >> 15) & 0x00000001; | 
|---|
 | 280 |             register int e = (y >> 10) & 0x0000001f; | 
|---|
 | 281 |             register int m =  y        & 0x000003ff; | 
|---|
 | 282 |          | 
|---|
 | 283 |             if (e == 0) | 
|---|
 | 284 |             { | 
|---|
 | 285 |                 if (m == 0) // Plus or minus zero | 
|---|
 | 286 |                 { | 
|---|
 | 287 |                     return s << 31; | 
|---|
 | 288 |                 } | 
|---|
 | 289 |                 else // Denormalized number -- renormalize it | 
|---|
 | 290 |                 { | 
|---|
 | 291 |                     while (!(m & 0x00000400)) | 
|---|
 | 292 |                     { | 
|---|
 | 293 |                         m <<= 1; | 
|---|
 | 294 |                         e -=  1; | 
|---|
 | 295 |                     } | 
|---|
 | 296 |          | 
|---|
 | 297 |                     e += 1; | 
|---|
 | 298 |                     m &= ~0x00000400; | 
|---|
 | 299 |                 } | 
|---|
 | 300 |             } | 
|---|
 | 301 |             else if (e == 31) | 
|---|
 | 302 |             { | 
|---|
 | 303 |                 if (m == 0) // Inf | 
|---|
 | 304 |                 { | 
|---|
 | 305 |                     return (s << 31) | 0x7f800000; | 
|---|
 | 306 |                 } | 
|---|
 | 307 |                 else // NaN | 
|---|
 | 308 |                 { | 
|---|
 | 309 |                     return (s << 31) | 0x7f800000 | (m << 13); | 
|---|
 | 310 |                 } | 
|---|
 | 311 |             } | 
|---|
 | 312 |          | 
|---|
 | 313 |             e = e + (127 - 15); | 
|---|
 | 314 |             m = m << 13; | 
|---|
 | 315 |          | 
|---|
 | 316 |             return (s << 31) | (e << 23) | m; | 
|---|
 | 317 |         } | 
|---|
 | 318 |           | 
|---|
 | 319 |  | 
|---|
 | 320 |     }; | 
|---|
 | 321 | } | 
|---|
 | 322 |  | 
|---|
 | 323 | #endif | 
|---|