1bf215546Sopenharmony_ci/************************************************************************** 2bf215546Sopenharmony_ci * 3bf215546Sopenharmony_ci * Copyright 2008 VMware, Inc. 4bf215546Sopenharmony_ci * All Rights Reserved. 5bf215546Sopenharmony_ci * 6bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 7bf215546Sopenharmony_ci * copy of this software and associated documentation files (the 8bf215546Sopenharmony_ci * "Software"), to deal in the Software without restriction, including 9bf215546Sopenharmony_ci * without limitation the rights to use, copy, modify, merge, publish, 10bf215546Sopenharmony_ci * distribute, sub license, and/or sell copies of the Software, and to 11bf215546Sopenharmony_ci * permit persons to whom the Software is furnished to do so, subject to 12bf215546Sopenharmony_ci * the following conditions: 13bf215546Sopenharmony_ci * 14bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the 15bf215546Sopenharmony_ci * next paragraph) shall be included in all copies or substantial portions 16bf215546Sopenharmony_ci * of the Software. 17bf215546Sopenharmony_ci * 18bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19bf215546Sopenharmony_ci * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20bf215546Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 21bf215546Sopenharmony_ci * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR 22bf215546Sopenharmony_ci * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23bf215546Sopenharmony_ci * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24bf215546Sopenharmony_ci * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25bf215546Sopenharmony_ci * 26bf215546Sopenharmony_ci **************************************************************************/ 27bf215546Sopenharmony_ci 28bf215546Sopenharmony_ci 29bf215546Sopenharmony_ci/** 30bf215546Sopenharmony_ci * Math utilities and approximations for common math functions. 31bf215546Sopenharmony_ci * Reduced precision is usually acceptable in shaders... 32bf215546Sopenharmony_ci * 33bf215546Sopenharmony_ci * "fast" is used in the names of functions which are low-precision, 34bf215546Sopenharmony_ci * or at least lower-precision than the normal C lib functions. 35bf215546Sopenharmony_ci */ 36bf215546Sopenharmony_ci 37bf215546Sopenharmony_ci 38bf215546Sopenharmony_ci#ifndef U_MATH_H 39bf215546Sopenharmony_ci#define U_MATH_H 40bf215546Sopenharmony_ci 41bf215546Sopenharmony_ci 42bf215546Sopenharmony_ci#include "c99_compat.h" 43bf215546Sopenharmony_ci#include <assert.h> 44bf215546Sopenharmony_ci#include <float.h> 45bf215546Sopenharmony_ci#include <stdarg.h> 46bf215546Sopenharmony_ci#include <math.h> 47bf215546Sopenharmony_ci 48bf215546Sopenharmony_ci#include "bitscan.h" 49bf215546Sopenharmony_ci#include "u_endian.h" /* for UTIL_ARCH_BIG_ENDIAN */ 50bf215546Sopenharmony_ci 51bf215546Sopenharmony_ci#ifdef __cplusplus 52bf215546Sopenharmony_ciextern "C" { 53bf215546Sopenharmony_ci#endif 54bf215546Sopenharmony_ci 55bf215546Sopenharmony_ci 56bf215546Sopenharmony_ci#ifndef M_SQRT2 57bf215546Sopenharmony_ci#define M_SQRT2 1.41421356237309504880 58bf215546Sopenharmony_ci#endif 59bf215546Sopenharmony_ci 60bf215546Sopenharmony_ci 61bf215546Sopenharmony_ci/** 62bf215546Sopenharmony_ci * Initialize math module. This should be called before using any 63bf215546Sopenharmony_ci * other functions in this module. 64bf215546Sopenharmony_ci */ 65bf215546Sopenharmony_ciextern void 66bf215546Sopenharmony_ciutil_init_math(void); 67bf215546Sopenharmony_ci 68bf215546Sopenharmony_ci 69bf215546Sopenharmony_ciunion fi { 70bf215546Sopenharmony_ci float f; 71bf215546Sopenharmony_ci int32_t i; 72bf215546Sopenharmony_ci uint32_t ui; 73bf215546Sopenharmony_ci}; 74bf215546Sopenharmony_ci 75bf215546Sopenharmony_ci 76bf215546Sopenharmony_ciunion di { 77bf215546Sopenharmony_ci double d; 78bf215546Sopenharmony_ci int64_t i; 79bf215546Sopenharmony_ci uint64_t ui; 80bf215546Sopenharmony_ci}; 81bf215546Sopenharmony_ci 82bf215546Sopenharmony_ci 83bf215546Sopenharmony_ci/** 84bf215546Sopenharmony_ci * Extract the IEEE float32 exponent. 85bf215546Sopenharmony_ci */ 86bf215546Sopenharmony_cistatic inline signed 87bf215546Sopenharmony_ciutil_get_float32_exponent(float x) 88bf215546Sopenharmony_ci{ 89bf215546Sopenharmony_ci union fi f; 90bf215546Sopenharmony_ci 91bf215546Sopenharmony_ci f.f = x; 92bf215546Sopenharmony_ci 93bf215546Sopenharmony_ci return ((f.ui >> 23) & 0xff) - 127; 94bf215546Sopenharmony_ci} 95bf215546Sopenharmony_ci 96bf215546Sopenharmony_ci 97bf215546Sopenharmony_ci#define LOG2_TABLE_SIZE_LOG2 8 98bf215546Sopenharmony_ci#define LOG2_TABLE_SCALE (1 << LOG2_TABLE_SIZE_LOG2) 99bf215546Sopenharmony_ci#define LOG2_TABLE_SIZE (LOG2_TABLE_SCALE + 1) 100bf215546Sopenharmony_ciextern float log2_table[LOG2_TABLE_SIZE]; 101bf215546Sopenharmony_ci 102bf215546Sopenharmony_ci 103bf215546Sopenharmony_ci/** 104bf215546Sopenharmony_ci * Fast approximation to log2(x). 105bf215546Sopenharmony_ci */ 106bf215546Sopenharmony_cistatic inline float 107bf215546Sopenharmony_ciutil_fast_log2(float x) 108bf215546Sopenharmony_ci{ 109bf215546Sopenharmony_ci union fi num; 110bf215546Sopenharmony_ci float epart, mpart; 111bf215546Sopenharmony_ci num.f = x; 112bf215546Sopenharmony_ci epart = (float)(((num.i & 0x7f800000) >> 23) - 127); 113bf215546Sopenharmony_ci /* mpart = log2_table[mantissa*LOG2_TABLE_SCALE + 0.5] */ 114bf215546Sopenharmony_ci mpart = log2_table[((num.i & 0x007fffff) + (1 << (22 - LOG2_TABLE_SIZE_LOG2))) >> (23 - LOG2_TABLE_SIZE_LOG2)]; 115bf215546Sopenharmony_ci return epart + mpart; 116bf215546Sopenharmony_ci} 117bf215546Sopenharmony_ci 118bf215546Sopenharmony_ci 119bf215546Sopenharmony_ci/** 120bf215546Sopenharmony_ci * Floor(x), returned as int. 121bf215546Sopenharmony_ci */ 122bf215546Sopenharmony_cistatic inline int 123bf215546Sopenharmony_ciutil_ifloor(float f) 124bf215546Sopenharmony_ci{ 125bf215546Sopenharmony_ci#if defined(USE_X86_ASM) && defined(__GNUC__) && defined(__i386__) 126bf215546Sopenharmony_ci /* 127bf215546Sopenharmony_ci * IEEE floor for computers that round to nearest or even. 128bf215546Sopenharmony_ci * 'f' must be between -4194304 and 4194303. 129bf215546Sopenharmony_ci * This floor operation is done by "(iround(f + .5) + iround(f - .5)) >> 1", 130bf215546Sopenharmony_ci * but uses some IEEE specific tricks for better speed. 131bf215546Sopenharmony_ci * Contributed by Josh Vanderhoof 132bf215546Sopenharmony_ci */ 133bf215546Sopenharmony_ci int ai, bi; 134bf215546Sopenharmony_ci double af, bf; 135bf215546Sopenharmony_ci af = (3 << 22) + 0.5 + (double)f; 136bf215546Sopenharmony_ci bf = (3 << 22) + 0.5 - (double)f; 137bf215546Sopenharmony_ci /* GCC generates an extra fstp/fld without this. */ 138bf215546Sopenharmony_ci __asm__ ("fstps %0" : "=m" (ai) : "t" (af) : "st"); 139bf215546Sopenharmony_ci __asm__ ("fstps %0" : "=m" (bi) : "t" (bf) : "st"); 140bf215546Sopenharmony_ci return (ai - bi) >> 1; 141bf215546Sopenharmony_ci#else 142bf215546Sopenharmony_ci int ai, bi; 143bf215546Sopenharmony_ci double af, bf; 144bf215546Sopenharmony_ci union fi u; 145bf215546Sopenharmony_ci af = (3 << 22) + 0.5 + (double) f; 146bf215546Sopenharmony_ci bf = (3 << 22) + 0.5 - (double) f; 147bf215546Sopenharmony_ci u.f = (float) af; ai = u.i; 148bf215546Sopenharmony_ci u.f = (float) bf; bi = u.i; 149bf215546Sopenharmony_ci return (ai - bi) >> 1; 150bf215546Sopenharmony_ci#endif 151bf215546Sopenharmony_ci} 152bf215546Sopenharmony_ci 153bf215546Sopenharmony_ci 154bf215546Sopenharmony_ci/** 155bf215546Sopenharmony_ci * Round float to nearest int. 156bf215546Sopenharmony_ci */ 157bf215546Sopenharmony_cistatic inline int 158bf215546Sopenharmony_ciutil_iround(float f) 159bf215546Sopenharmony_ci{ 160bf215546Sopenharmony_ci#if defined(PIPE_CC_GCC) && defined(PIPE_ARCH_X86) 161bf215546Sopenharmony_ci int r; 162bf215546Sopenharmony_ci __asm__ ("fistpl %0" : "=m" (r) : "t" (f) : "st"); 163bf215546Sopenharmony_ci return r; 164bf215546Sopenharmony_ci#elif defined(PIPE_CC_MSVC) && defined(PIPE_ARCH_X86) 165bf215546Sopenharmony_ci int r; 166bf215546Sopenharmony_ci _asm { 167bf215546Sopenharmony_ci fld f 168bf215546Sopenharmony_ci fistp r 169bf215546Sopenharmony_ci } 170bf215546Sopenharmony_ci return r; 171bf215546Sopenharmony_ci#else 172bf215546Sopenharmony_ci if (f >= 0.0f) 173bf215546Sopenharmony_ci return (int) (f + 0.5f); 174bf215546Sopenharmony_ci else 175bf215546Sopenharmony_ci return (int) (f - 0.5f); 176bf215546Sopenharmony_ci#endif 177bf215546Sopenharmony_ci} 178bf215546Sopenharmony_ci 179bf215546Sopenharmony_ci 180bf215546Sopenharmony_ci/** 181bf215546Sopenharmony_ci * Approximate floating point comparison 182bf215546Sopenharmony_ci */ 183bf215546Sopenharmony_cistatic inline bool 184bf215546Sopenharmony_ciutil_is_approx(float a, float b, float tol) 185bf215546Sopenharmony_ci{ 186bf215546Sopenharmony_ci return fabsf(b - a) <= tol; 187bf215546Sopenharmony_ci} 188bf215546Sopenharmony_ci 189bf215546Sopenharmony_ci 190bf215546Sopenharmony_ci/** 191bf215546Sopenharmony_ci * util_is_X_inf_or_nan = test if x is NaN or +/- Inf 192bf215546Sopenharmony_ci * util_is_X_nan = test if x is NaN 193bf215546Sopenharmony_ci * util_X_inf_sign = return +1 for +Inf, -1 for -Inf, or 0 for not Inf 194bf215546Sopenharmony_ci * 195bf215546Sopenharmony_ci * NaN can be checked with x != x, however this fails with the fast math flag 196bf215546Sopenharmony_ci **/ 197bf215546Sopenharmony_ci 198bf215546Sopenharmony_ci 199bf215546Sopenharmony_ci/** 200bf215546Sopenharmony_ci * Single-float 201bf215546Sopenharmony_ci */ 202bf215546Sopenharmony_cistatic inline bool 203bf215546Sopenharmony_ciutil_is_inf_or_nan(float x) 204bf215546Sopenharmony_ci{ 205bf215546Sopenharmony_ci union fi tmp; 206bf215546Sopenharmony_ci tmp.f = x; 207bf215546Sopenharmony_ci return (tmp.ui & 0x7f800000) == 0x7f800000; 208bf215546Sopenharmony_ci} 209bf215546Sopenharmony_ci 210bf215546Sopenharmony_ci 211bf215546Sopenharmony_cistatic inline bool 212bf215546Sopenharmony_ciutil_is_nan(float x) 213bf215546Sopenharmony_ci{ 214bf215546Sopenharmony_ci union fi tmp; 215bf215546Sopenharmony_ci tmp.f = x; 216bf215546Sopenharmony_ci return (tmp.ui & 0x7fffffff) > 0x7f800000; 217bf215546Sopenharmony_ci} 218bf215546Sopenharmony_ci 219bf215546Sopenharmony_ci 220bf215546Sopenharmony_cistatic inline int 221bf215546Sopenharmony_ciutil_inf_sign(float x) 222bf215546Sopenharmony_ci{ 223bf215546Sopenharmony_ci union fi tmp; 224bf215546Sopenharmony_ci tmp.f = x; 225bf215546Sopenharmony_ci if ((tmp.ui & 0x7fffffff) != 0x7f800000) { 226bf215546Sopenharmony_ci return 0; 227bf215546Sopenharmony_ci } 228bf215546Sopenharmony_ci 229bf215546Sopenharmony_ci return (x < 0) ? -1 : 1; 230bf215546Sopenharmony_ci} 231bf215546Sopenharmony_ci 232bf215546Sopenharmony_ci 233bf215546Sopenharmony_ci/** 234bf215546Sopenharmony_ci * Double-float 235bf215546Sopenharmony_ci */ 236bf215546Sopenharmony_cistatic inline bool 237bf215546Sopenharmony_ciutil_is_double_inf_or_nan(double x) 238bf215546Sopenharmony_ci{ 239bf215546Sopenharmony_ci union di tmp; 240bf215546Sopenharmony_ci tmp.d = x; 241bf215546Sopenharmony_ci return (tmp.ui & 0x7ff0000000000000ULL) == 0x7ff0000000000000ULL; 242bf215546Sopenharmony_ci} 243bf215546Sopenharmony_ci 244bf215546Sopenharmony_ci 245bf215546Sopenharmony_cistatic inline bool 246bf215546Sopenharmony_ciutil_is_double_nan(double x) 247bf215546Sopenharmony_ci{ 248bf215546Sopenharmony_ci union di tmp; 249bf215546Sopenharmony_ci tmp.d = x; 250bf215546Sopenharmony_ci return (tmp.ui & 0x7fffffffffffffffULL) > 0x7ff0000000000000ULL; 251bf215546Sopenharmony_ci} 252bf215546Sopenharmony_ci 253bf215546Sopenharmony_ci 254bf215546Sopenharmony_cistatic inline int 255bf215546Sopenharmony_ciutil_double_inf_sign(double x) 256bf215546Sopenharmony_ci{ 257bf215546Sopenharmony_ci union di tmp; 258bf215546Sopenharmony_ci tmp.d = x; 259bf215546Sopenharmony_ci if ((tmp.ui & 0x7fffffffffffffffULL) != 0x7ff0000000000000ULL) { 260bf215546Sopenharmony_ci return 0; 261bf215546Sopenharmony_ci } 262bf215546Sopenharmony_ci 263bf215546Sopenharmony_ci return (x < 0) ? -1 : 1; 264bf215546Sopenharmony_ci} 265bf215546Sopenharmony_ci 266bf215546Sopenharmony_ci 267bf215546Sopenharmony_ci/** 268bf215546Sopenharmony_ci * Half-float 269bf215546Sopenharmony_ci */ 270bf215546Sopenharmony_cistatic inline bool 271bf215546Sopenharmony_ciutil_is_half_inf_or_nan(int16_t x) 272bf215546Sopenharmony_ci{ 273bf215546Sopenharmony_ci return (x & 0x7c00) == 0x7c00; 274bf215546Sopenharmony_ci} 275bf215546Sopenharmony_ci 276bf215546Sopenharmony_ci 277bf215546Sopenharmony_cistatic inline bool 278bf215546Sopenharmony_ciutil_is_half_nan(int16_t x) 279bf215546Sopenharmony_ci{ 280bf215546Sopenharmony_ci return (x & 0x7fff) > 0x7c00; 281bf215546Sopenharmony_ci} 282bf215546Sopenharmony_ci 283bf215546Sopenharmony_ci 284bf215546Sopenharmony_cistatic inline int 285bf215546Sopenharmony_ciutil_half_inf_sign(int16_t x) 286bf215546Sopenharmony_ci{ 287bf215546Sopenharmony_ci if ((x & 0x7fff) != 0x7c00) { 288bf215546Sopenharmony_ci return 0; 289bf215546Sopenharmony_ci } 290bf215546Sopenharmony_ci 291bf215546Sopenharmony_ci return (x < 0) ? -1 : 1; 292bf215546Sopenharmony_ci} 293bf215546Sopenharmony_ci 294bf215546Sopenharmony_ci 295bf215546Sopenharmony_ci/** 296bf215546Sopenharmony_ci * Return float bits. 297bf215546Sopenharmony_ci */ 298bf215546Sopenharmony_cistatic inline unsigned 299bf215546Sopenharmony_cifui( float f ) 300bf215546Sopenharmony_ci{ 301bf215546Sopenharmony_ci union fi fi; 302bf215546Sopenharmony_ci fi.f = f; 303bf215546Sopenharmony_ci return fi.ui; 304bf215546Sopenharmony_ci} 305bf215546Sopenharmony_ci 306bf215546Sopenharmony_cistatic inline float 307bf215546Sopenharmony_ciuif(uint32_t ui) 308bf215546Sopenharmony_ci{ 309bf215546Sopenharmony_ci union fi fi; 310bf215546Sopenharmony_ci fi.ui = ui; 311bf215546Sopenharmony_ci return fi.f; 312bf215546Sopenharmony_ci} 313bf215546Sopenharmony_ci 314bf215546Sopenharmony_ci 315bf215546Sopenharmony_ci/** 316bf215546Sopenharmony_ci * Convert uint8_t to float in [0, 1]. 317bf215546Sopenharmony_ci */ 318bf215546Sopenharmony_cistatic inline float 319bf215546Sopenharmony_ciubyte_to_float(uint8_t ub) 320bf215546Sopenharmony_ci{ 321bf215546Sopenharmony_ci return (float) ub * (1.0f / 255.0f); 322bf215546Sopenharmony_ci} 323bf215546Sopenharmony_ci 324bf215546Sopenharmony_ci 325bf215546Sopenharmony_ci/** 326bf215546Sopenharmony_ci * Convert float in [0,1] to uint8_t in [0,255] with clamping. 327bf215546Sopenharmony_ci */ 328bf215546Sopenharmony_cistatic inline uint8_t 329bf215546Sopenharmony_cifloat_to_ubyte(float f) 330bf215546Sopenharmony_ci{ 331bf215546Sopenharmony_ci /* return 0 for NaN too */ 332bf215546Sopenharmony_ci if (!(f > 0.0f)) { 333bf215546Sopenharmony_ci return (uint8_t) 0; 334bf215546Sopenharmony_ci } 335bf215546Sopenharmony_ci else if (f >= 1.0f) { 336bf215546Sopenharmony_ci return (uint8_t) 255; 337bf215546Sopenharmony_ci } 338bf215546Sopenharmony_ci else { 339bf215546Sopenharmony_ci union fi tmp; 340bf215546Sopenharmony_ci tmp.f = f; 341bf215546Sopenharmony_ci tmp.f = tmp.f * (255.0f/256.0f) + 32768.0f; 342bf215546Sopenharmony_ci return (uint8_t) tmp.i; 343bf215546Sopenharmony_ci } 344bf215546Sopenharmony_ci} 345bf215546Sopenharmony_ci 346bf215546Sopenharmony_ci/** 347bf215546Sopenharmony_ci * Convert uint16_t to float in [0, 1]. 348bf215546Sopenharmony_ci */ 349bf215546Sopenharmony_cistatic inline float 350bf215546Sopenharmony_ciushort_to_float(uint16_t us) 351bf215546Sopenharmony_ci{ 352bf215546Sopenharmony_ci return (float) us * (1.0f / 65535.0f); 353bf215546Sopenharmony_ci} 354bf215546Sopenharmony_ci 355bf215546Sopenharmony_ci 356bf215546Sopenharmony_ci/** 357bf215546Sopenharmony_ci * Convert float in [0,1] to uint16_t in [0,65535] with clamping. 358bf215546Sopenharmony_ci */ 359bf215546Sopenharmony_cistatic inline uint16_t 360bf215546Sopenharmony_cifloat_to_ushort(float f) 361bf215546Sopenharmony_ci{ 362bf215546Sopenharmony_ci /* return 0 for NaN too */ 363bf215546Sopenharmony_ci if (!(f > 0.0f)) { 364bf215546Sopenharmony_ci return (uint16_t) 0; 365bf215546Sopenharmony_ci } 366bf215546Sopenharmony_ci else if (f >= 1.0f) { 367bf215546Sopenharmony_ci return (uint16_t) 65535; 368bf215546Sopenharmony_ci } 369bf215546Sopenharmony_ci else { 370bf215546Sopenharmony_ci union fi tmp; 371bf215546Sopenharmony_ci tmp.f = f; 372bf215546Sopenharmony_ci tmp.f = tmp.f * (65535.0f/65536.0f) + 128.0f; 373bf215546Sopenharmony_ci return (uint16_t) tmp.i; 374bf215546Sopenharmony_ci } 375bf215546Sopenharmony_ci} 376bf215546Sopenharmony_ci 377bf215546Sopenharmony_cistatic inline float 378bf215546Sopenharmony_cibyte_to_float_tex(int8_t b) 379bf215546Sopenharmony_ci{ 380bf215546Sopenharmony_ci return (b == -128) ? -1.0F : b * 1.0F / 127.0F; 381bf215546Sopenharmony_ci} 382bf215546Sopenharmony_ci 383bf215546Sopenharmony_cistatic inline int8_t 384bf215546Sopenharmony_cifloat_to_byte_tex(float f) 385bf215546Sopenharmony_ci{ 386bf215546Sopenharmony_ci return (int8_t) (127.0F * f); 387bf215546Sopenharmony_ci} 388bf215546Sopenharmony_ci 389bf215546Sopenharmony_ci/** 390bf215546Sopenharmony_ci * Calc log base 2 391bf215546Sopenharmony_ci */ 392bf215546Sopenharmony_cistatic inline unsigned 393bf215546Sopenharmony_ciutil_logbase2(unsigned n) 394bf215546Sopenharmony_ci{ 395bf215546Sopenharmony_ci#if defined(HAVE___BUILTIN_CLZ) 396bf215546Sopenharmony_ci return ((sizeof(unsigned) * 8 - 1) - __builtin_clz(n | 1)); 397bf215546Sopenharmony_ci#else 398bf215546Sopenharmony_ci unsigned pos = 0; 399bf215546Sopenharmony_ci if (n >= 1<<16) { n >>= 16; pos += 16; } 400bf215546Sopenharmony_ci if (n >= 1<< 8) { n >>= 8; pos += 8; } 401bf215546Sopenharmony_ci if (n >= 1<< 4) { n >>= 4; pos += 4; } 402bf215546Sopenharmony_ci if (n >= 1<< 2) { n >>= 2; pos += 2; } 403bf215546Sopenharmony_ci if (n >= 1<< 1) { pos += 1; } 404bf215546Sopenharmony_ci return pos; 405bf215546Sopenharmony_ci#endif 406bf215546Sopenharmony_ci} 407bf215546Sopenharmony_ci 408bf215546Sopenharmony_cistatic inline uint64_t 409bf215546Sopenharmony_ciutil_logbase2_64(uint64_t n) 410bf215546Sopenharmony_ci{ 411bf215546Sopenharmony_ci#if defined(HAVE___BUILTIN_CLZLL) 412bf215546Sopenharmony_ci return ((sizeof(uint64_t) * 8 - 1) - __builtin_clzll(n | 1)); 413bf215546Sopenharmony_ci#else 414bf215546Sopenharmony_ci uint64_t pos = 0ull; 415bf215546Sopenharmony_ci if (n >= 1ull<<32) { n >>= 32; pos += 32; } 416bf215546Sopenharmony_ci if (n >= 1ull<<16) { n >>= 16; pos += 16; } 417bf215546Sopenharmony_ci if (n >= 1ull<< 8) { n >>= 8; pos += 8; } 418bf215546Sopenharmony_ci if (n >= 1ull<< 4) { n >>= 4; pos += 4; } 419bf215546Sopenharmony_ci if (n >= 1ull<< 2) { n >>= 2; pos += 2; } 420bf215546Sopenharmony_ci if (n >= 1ull<< 1) { pos += 1; } 421bf215546Sopenharmony_ci return pos; 422bf215546Sopenharmony_ci#endif 423bf215546Sopenharmony_ci} 424bf215546Sopenharmony_ci 425bf215546Sopenharmony_ci/** 426bf215546Sopenharmony_ci * Returns the ceiling of log n base 2, and 0 when n == 0. Equivalently, 427bf215546Sopenharmony_ci * returns the smallest x such that n <= 2**x. 428bf215546Sopenharmony_ci */ 429bf215546Sopenharmony_cistatic inline unsigned 430bf215546Sopenharmony_ciutil_logbase2_ceil(unsigned n) 431bf215546Sopenharmony_ci{ 432bf215546Sopenharmony_ci if (n <= 1) 433bf215546Sopenharmony_ci return 0; 434bf215546Sopenharmony_ci 435bf215546Sopenharmony_ci return 1 + util_logbase2(n - 1); 436bf215546Sopenharmony_ci} 437bf215546Sopenharmony_ci 438bf215546Sopenharmony_cistatic inline uint64_t 439bf215546Sopenharmony_ciutil_logbase2_ceil64(uint64_t n) 440bf215546Sopenharmony_ci{ 441bf215546Sopenharmony_ci if (n <= 1) 442bf215546Sopenharmony_ci return 0; 443bf215546Sopenharmony_ci 444bf215546Sopenharmony_ci return 1ull + util_logbase2_64(n - 1); 445bf215546Sopenharmony_ci} 446bf215546Sopenharmony_ci 447bf215546Sopenharmony_ci/** 448bf215546Sopenharmony_ci * Returns the smallest power of two >= x 449bf215546Sopenharmony_ci */ 450bf215546Sopenharmony_cistatic inline unsigned 451bf215546Sopenharmony_ciutil_next_power_of_two(unsigned x) 452bf215546Sopenharmony_ci{ 453bf215546Sopenharmony_ci#if defined(HAVE___BUILTIN_CLZ) 454bf215546Sopenharmony_ci if (x <= 1) 455bf215546Sopenharmony_ci return 1; 456bf215546Sopenharmony_ci 457bf215546Sopenharmony_ci return (1 << ((sizeof(unsigned) * 8) - __builtin_clz(x - 1))); 458bf215546Sopenharmony_ci#else 459bf215546Sopenharmony_ci unsigned val = x; 460bf215546Sopenharmony_ci 461bf215546Sopenharmony_ci if (x <= 1) 462bf215546Sopenharmony_ci return 1; 463bf215546Sopenharmony_ci 464bf215546Sopenharmony_ci if (util_is_power_of_two_or_zero(x)) 465bf215546Sopenharmony_ci return x; 466bf215546Sopenharmony_ci 467bf215546Sopenharmony_ci val--; 468bf215546Sopenharmony_ci val = (val >> 1) | val; 469bf215546Sopenharmony_ci val = (val >> 2) | val; 470bf215546Sopenharmony_ci val = (val >> 4) | val; 471bf215546Sopenharmony_ci val = (val >> 8) | val; 472bf215546Sopenharmony_ci val = (val >> 16) | val; 473bf215546Sopenharmony_ci val++; 474bf215546Sopenharmony_ci return val; 475bf215546Sopenharmony_ci#endif 476bf215546Sopenharmony_ci} 477bf215546Sopenharmony_ci 478bf215546Sopenharmony_cistatic inline uint64_t 479bf215546Sopenharmony_ciutil_next_power_of_two64(uint64_t x) 480bf215546Sopenharmony_ci{ 481bf215546Sopenharmony_ci#if defined(HAVE___BUILTIN_CLZLL) 482bf215546Sopenharmony_ci if (x <= 1) 483bf215546Sopenharmony_ci return 1; 484bf215546Sopenharmony_ci 485bf215546Sopenharmony_ci return (1ull << ((sizeof(uint64_t) * 8) - __builtin_clzll(x - 1))); 486bf215546Sopenharmony_ci#else 487bf215546Sopenharmony_ci uint64_t val = x; 488bf215546Sopenharmony_ci 489bf215546Sopenharmony_ci if (x <= 1) 490bf215546Sopenharmony_ci return 1; 491bf215546Sopenharmony_ci 492bf215546Sopenharmony_ci if (util_is_power_of_two_or_zero64(x)) 493bf215546Sopenharmony_ci return x; 494bf215546Sopenharmony_ci 495bf215546Sopenharmony_ci val--; 496bf215546Sopenharmony_ci val = (val >> 1) | val; 497bf215546Sopenharmony_ci val = (val >> 2) | val; 498bf215546Sopenharmony_ci val = (val >> 4) | val; 499bf215546Sopenharmony_ci val = (val >> 8) | val; 500bf215546Sopenharmony_ci val = (val >> 16) | val; 501bf215546Sopenharmony_ci val = (val >> 32) | val; 502bf215546Sopenharmony_ci val++; 503bf215546Sopenharmony_ci return val; 504bf215546Sopenharmony_ci#endif 505bf215546Sopenharmony_ci} 506bf215546Sopenharmony_ci 507bf215546Sopenharmony_ci/** 508bf215546Sopenharmony_ci * Reverse bits in n 509bf215546Sopenharmony_ci * Algorithm taken from: 510bf215546Sopenharmony_ci * http://stackoverflow.com/questions/9144800/c-reverse-bits-in-unsigned-integer 511bf215546Sopenharmony_ci */ 512bf215546Sopenharmony_cistatic inline unsigned 513bf215546Sopenharmony_ciutil_bitreverse(unsigned n) 514bf215546Sopenharmony_ci{ 515bf215546Sopenharmony_ci n = ((n >> 1) & 0x55555555u) | ((n & 0x55555555u) << 1); 516bf215546Sopenharmony_ci n = ((n >> 2) & 0x33333333u) | ((n & 0x33333333u) << 2); 517bf215546Sopenharmony_ci n = ((n >> 4) & 0x0f0f0f0fu) | ((n & 0x0f0f0f0fu) << 4); 518bf215546Sopenharmony_ci n = ((n >> 8) & 0x00ff00ffu) | ((n & 0x00ff00ffu) << 8); 519bf215546Sopenharmony_ci n = ((n >> 16) & 0xffffu) | ((n & 0xffffu) << 16); 520bf215546Sopenharmony_ci return n; 521bf215546Sopenharmony_ci} 522bf215546Sopenharmony_ci 523bf215546Sopenharmony_ci/** 524bf215546Sopenharmony_ci * Convert from little endian to CPU byte order. 525bf215546Sopenharmony_ci */ 526bf215546Sopenharmony_ci 527bf215546Sopenharmony_ci#if UTIL_ARCH_BIG_ENDIAN 528bf215546Sopenharmony_ci#define util_le64_to_cpu(x) util_bswap64(x) 529bf215546Sopenharmony_ci#define util_le32_to_cpu(x) util_bswap32(x) 530bf215546Sopenharmony_ci#define util_le16_to_cpu(x) util_bswap16(x) 531bf215546Sopenharmony_ci#else 532bf215546Sopenharmony_ci#define util_le64_to_cpu(x) (x) 533bf215546Sopenharmony_ci#define util_le32_to_cpu(x) (x) 534bf215546Sopenharmony_ci#define util_le16_to_cpu(x) (x) 535bf215546Sopenharmony_ci#endif 536bf215546Sopenharmony_ci 537bf215546Sopenharmony_ci#define util_cpu_to_le64(x) util_le64_to_cpu(x) 538bf215546Sopenharmony_ci#define util_cpu_to_le32(x) util_le32_to_cpu(x) 539bf215546Sopenharmony_ci#define util_cpu_to_le16(x) util_le16_to_cpu(x) 540bf215546Sopenharmony_ci 541bf215546Sopenharmony_ci/** 542bf215546Sopenharmony_ci * Reverse byte order of a 32 bit word. 543bf215546Sopenharmony_ci */ 544bf215546Sopenharmony_cistatic inline uint32_t 545bf215546Sopenharmony_ciutil_bswap32(uint32_t n) 546bf215546Sopenharmony_ci{ 547bf215546Sopenharmony_ci#if defined(HAVE___BUILTIN_BSWAP32) 548bf215546Sopenharmony_ci return __builtin_bswap32(n); 549bf215546Sopenharmony_ci#else 550bf215546Sopenharmony_ci return (n >> 24) | 551bf215546Sopenharmony_ci ((n >> 8) & 0x0000ff00) | 552bf215546Sopenharmony_ci ((n << 8) & 0x00ff0000) | 553bf215546Sopenharmony_ci (n << 24); 554bf215546Sopenharmony_ci#endif 555bf215546Sopenharmony_ci} 556bf215546Sopenharmony_ci 557bf215546Sopenharmony_ci/** 558bf215546Sopenharmony_ci * Reverse byte order of a 64bit word. 559bf215546Sopenharmony_ci */ 560bf215546Sopenharmony_cistatic inline uint64_t 561bf215546Sopenharmony_ciutil_bswap64(uint64_t n) 562bf215546Sopenharmony_ci{ 563bf215546Sopenharmony_ci#if defined(HAVE___BUILTIN_BSWAP64) 564bf215546Sopenharmony_ci return __builtin_bswap64(n); 565bf215546Sopenharmony_ci#else 566bf215546Sopenharmony_ci return ((uint64_t)util_bswap32((uint32_t)n) << 32) | 567bf215546Sopenharmony_ci util_bswap32((n >> 32)); 568bf215546Sopenharmony_ci#endif 569bf215546Sopenharmony_ci} 570bf215546Sopenharmony_ci 571bf215546Sopenharmony_ci 572bf215546Sopenharmony_ci/** 573bf215546Sopenharmony_ci * Reverse byte order of a 16 bit word. 574bf215546Sopenharmony_ci */ 575bf215546Sopenharmony_cistatic inline uint16_t 576bf215546Sopenharmony_ciutil_bswap16(uint16_t n) 577bf215546Sopenharmony_ci{ 578bf215546Sopenharmony_ci return (n >> 8) | 579bf215546Sopenharmony_ci (n << 8); 580bf215546Sopenharmony_ci} 581bf215546Sopenharmony_ci 582bf215546Sopenharmony_ci/** 583bf215546Sopenharmony_ci * Mask and sign-extend a number 584bf215546Sopenharmony_ci * 585bf215546Sopenharmony_ci * The bit at position `width - 1` is replicated to all the higher bits. 586bf215546Sopenharmony_ci * This makes no assumptions about the high bits of the value and will 587bf215546Sopenharmony_ci * overwrite them with the sign bit. 588bf215546Sopenharmony_ci */ 589bf215546Sopenharmony_cistatic inline int64_t 590bf215546Sopenharmony_ciutil_mask_sign_extend(uint64_t val, unsigned width) 591bf215546Sopenharmony_ci{ 592bf215546Sopenharmony_ci assert(width > 0 && width <= 64); 593bf215546Sopenharmony_ci unsigned shift = 64 - width; 594bf215546Sopenharmony_ci return (int64_t)(val << shift) >> shift; 595bf215546Sopenharmony_ci} 596bf215546Sopenharmony_ci 597bf215546Sopenharmony_ci/** 598bf215546Sopenharmony_ci * Sign-extend a number 599bf215546Sopenharmony_ci * 600bf215546Sopenharmony_ci * The bit at position `width - 1` is replicated to all the higher bits. 601bf215546Sopenharmony_ci * This assumes and asserts that the value fits into `width` bits. 602bf215546Sopenharmony_ci */ 603bf215546Sopenharmony_cistatic inline int64_t 604bf215546Sopenharmony_ciutil_sign_extend(uint64_t val, unsigned width) 605bf215546Sopenharmony_ci{ 606bf215546Sopenharmony_ci assert(width == 64 || val < (UINT64_C(1) << width)); 607bf215546Sopenharmony_ci return util_mask_sign_extend(val, width); 608bf215546Sopenharmony_ci} 609bf215546Sopenharmony_ci 610bf215546Sopenharmony_cistatic inline void* 611bf215546Sopenharmony_ciutil_memcpy_cpu_to_le32(void * restrict dest, const void * restrict src, size_t n) 612bf215546Sopenharmony_ci{ 613bf215546Sopenharmony_ci#if UTIL_ARCH_BIG_ENDIAN 614bf215546Sopenharmony_ci size_t i, e; 615bf215546Sopenharmony_ci assert(n % 4 == 0); 616bf215546Sopenharmony_ci 617bf215546Sopenharmony_ci for (i = 0, e = n / 4; i < e; i++) { 618bf215546Sopenharmony_ci uint32_t * restrict d = (uint32_t* restrict)dest; 619bf215546Sopenharmony_ci const uint32_t * restrict s = (const uint32_t* restrict)src; 620bf215546Sopenharmony_ci d[i] = util_bswap32(s[i]); 621bf215546Sopenharmony_ci } 622bf215546Sopenharmony_ci return dest; 623bf215546Sopenharmony_ci#else 624bf215546Sopenharmony_ci return memcpy(dest, src, n); 625bf215546Sopenharmony_ci#endif 626bf215546Sopenharmony_ci} 627bf215546Sopenharmony_ci 628bf215546Sopenharmony_ci/** 629bf215546Sopenharmony_ci * Clamp X to [MIN, MAX]. 630bf215546Sopenharmony_ci * This is a macro to allow float, int, uint, etc. types. 631bf215546Sopenharmony_ci * We arbitrarily turn NaN into MIN. 632bf215546Sopenharmony_ci */ 633bf215546Sopenharmony_ci#define CLAMP( X, MIN, MAX ) ( (X)>(MIN) ? ((X)>(MAX) ? (MAX) : (X)) : (MIN) ) 634bf215546Sopenharmony_ci 635bf215546Sopenharmony_ci/* Syntax sugar occuring frequently in graphics code */ 636bf215546Sopenharmony_ci#define SATURATE( X ) CLAMP(X, 0.0f, 1.0f) 637bf215546Sopenharmony_ci 638bf215546Sopenharmony_ci#define MIN2( A, B ) ( (A)<(B) ? (A) : (B) ) 639bf215546Sopenharmony_ci#define MAX2( A, B ) ( (A)>(B) ? (A) : (B) ) 640bf215546Sopenharmony_ci 641bf215546Sopenharmony_ci#define MIN3( A, B, C ) ((A) < (B) ? MIN2(A, C) : MIN2(B, C)) 642bf215546Sopenharmony_ci#define MAX3( A, B, C ) ((A) > (B) ? MAX2(A, C) : MAX2(B, C)) 643bf215546Sopenharmony_ci 644bf215546Sopenharmony_ci#define MIN4( A, B, C, D ) ((A) < (B) ? MIN3(A, C, D) : MIN3(B, C, D)) 645bf215546Sopenharmony_ci#define MAX4( A, B, C, D ) ((A) > (B) ? MAX3(A, C, D) : MAX3(B, C, D)) 646bf215546Sopenharmony_ci 647bf215546Sopenharmony_ci 648bf215546Sopenharmony_ci/** 649bf215546Sopenharmony_ci * Align a value up to an alignment value 650bf215546Sopenharmony_ci * 651bf215546Sopenharmony_ci * If \c value is not already aligned to the requested alignment value, it 652bf215546Sopenharmony_ci * will be rounded up. 653bf215546Sopenharmony_ci * 654bf215546Sopenharmony_ci * \param value Value to be rounded 655bf215546Sopenharmony_ci * \param alignment Alignment value to be used. This must be a power of two. 656bf215546Sopenharmony_ci * 657bf215546Sopenharmony_ci * \sa ROUND_DOWN_TO() 658bf215546Sopenharmony_ci */ 659bf215546Sopenharmony_ci 660bf215546Sopenharmony_ci#if defined(ALIGN) 661bf215546Sopenharmony_ci#undef ALIGN 662bf215546Sopenharmony_ci#endif 663bf215546Sopenharmony_cistatic inline uintptr_t 664bf215546Sopenharmony_ciALIGN(uintptr_t value, int32_t alignment) 665bf215546Sopenharmony_ci{ 666bf215546Sopenharmony_ci assert(util_is_power_of_two_nonzero(alignment)); 667bf215546Sopenharmony_ci return (((value) + (alignment) - 1) & ~((alignment) - 1)); 668bf215546Sopenharmony_ci} 669bf215546Sopenharmony_ci 670bf215546Sopenharmony_ci/** 671bf215546Sopenharmony_ci * Like ALIGN(), but works with a non-power-of-two alignment. 672bf215546Sopenharmony_ci */ 673bf215546Sopenharmony_cistatic inline uintptr_t 674bf215546Sopenharmony_ciALIGN_NPOT(uintptr_t value, int32_t alignment) 675bf215546Sopenharmony_ci{ 676bf215546Sopenharmony_ci assert(alignment > 0); 677bf215546Sopenharmony_ci return (value + alignment - 1) / alignment * alignment; 678bf215546Sopenharmony_ci} 679bf215546Sopenharmony_ci 680bf215546Sopenharmony_ci/** 681bf215546Sopenharmony_ci * Align a value down to an alignment value 682bf215546Sopenharmony_ci * 683bf215546Sopenharmony_ci * If \c value is not already aligned to the requested alignment value, it 684bf215546Sopenharmony_ci * will be rounded down. 685bf215546Sopenharmony_ci * 686bf215546Sopenharmony_ci * \param value Value to be rounded 687bf215546Sopenharmony_ci * \param alignment Alignment value to be used. This must be a power of two. 688bf215546Sopenharmony_ci * 689bf215546Sopenharmony_ci * \sa ALIGN() 690bf215546Sopenharmony_ci */ 691bf215546Sopenharmony_cistatic inline uint64_t 692bf215546Sopenharmony_ciROUND_DOWN_TO(uint64_t value, int32_t alignment) 693bf215546Sopenharmony_ci{ 694bf215546Sopenharmony_ci assert(util_is_power_of_two_nonzero(alignment)); 695bf215546Sopenharmony_ci return ((value) & ~(alignment - 1)); 696bf215546Sopenharmony_ci} 697bf215546Sopenharmony_ci 698bf215546Sopenharmony_ci/** 699bf215546Sopenharmony_ci * Align a value, only works pot alignemnts. 700bf215546Sopenharmony_ci */ 701bf215546Sopenharmony_cistatic inline int 702bf215546Sopenharmony_cialign(int value, int alignment) 703bf215546Sopenharmony_ci{ 704bf215546Sopenharmony_ci return (value + alignment - 1) & ~(alignment - 1); 705bf215546Sopenharmony_ci} 706bf215546Sopenharmony_ci 707bf215546Sopenharmony_cistatic inline uint64_t 708bf215546Sopenharmony_cialign64(uint64_t value, unsigned alignment) 709bf215546Sopenharmony_ci{ 710bf215546Sopenharmony_ci return (value + alignment - 1) & ~((uint64_t)alignment - 1); 711bf215546Sopenharmony_ci} 712bf215546Sopenharmony_ci 713bf215546Sopenharmony_ci/** 714bf215546Sopenharmony_ci * Works like align but on npot alignments. 715bf215546Sopenharmony_ci */ 716bf215546Sopenharmony_cistatic inline size_t 717bf215546Sopenharmony_ciutil_align_npot(size_t value, size_t alignment) 718bf215546Sopenharmony_ci{ 719bf215546Sopenharmony_ci if (value % alignment) 720bf215546Sopenharmony_ci return value + (alignment - (value % alignment)); 721bf215546Sopenharmony_ci return value; 722bf215546Sopenharmony_ci} 723bf215546Sopenharmony_ci 724bf215546Sopenharmony_cistatic inline unsigned 725bf215546Sopenharmony_ciu_minify(unsigned value, unsigned levels) 726bf215546Sopenharmony_ci{ 727bf215546Sopenharmony_ci return MAX2(1, value >> levels); 728bf215546Sopenharmony_ci} 729bf215546Sopenharmony_ci 730bf215546Sopenharmony_ci#ifndef COPY_4V 731bf215546Sopenharmony_ci#define COPY_4V( DST, SRC ) \ 732bf215546Sopenharmony_cido { \ 733bf215546Sopenharmony_ci (DST)[0] = (SRC)[0]; \ 734bf215546Sopenharmony_ci (DST)[1] = (SRC)[1]; \ 735bf215546Sopenharmony_ci (DST)[2] = (SRC)[2]; \ 736bf215546Sopenharmony_ci (DST)[3] = (SRC)[3]; \ 737bf215546Sopenharmony_ci} while (0) 738bf215546Sopenharmony_ci#endif 739bf215546Sopenharmony_ci 740bf215546Sopenharmony_ci 741bf215546Sopenharmony_ci#ifndef COPY_4FV 742bf215546Sopenharmony_ci#define COPY_4FV( DST, SRC ) COPY_4V(DST, SRC) 743bf215546Sopenharmony_ci#endif 744bf215546Sopenharmony_ci 745bf215546Sopenharmony_ci 746bf215546Sopenharmony_ci#ifndef ASSIGN_4V 747bf215546Sopenharmony_ci#define ASSIGN_4V( DST, V0, V1, V2, V3 ) \ 748bf215546Sopenharmony_cido { \ 749bf215546Sopenharmony_ci (DST)[0] = (V0); \ 750bf215546Sopenharmony_ci (DST)[1] = (V1); \ 751bf215546Sopenharmony_ci (DST)[2] = (V2); \ 752bf215546Sopenharmony_ci (DST)[3] = (V3); \ 753bf215546Sopenharmony_ci} while (0) 754bf215546Sopenharmony_ci#endif 755bf215546Sopenharmony_ci 756bf215546Sopenharmony_ci 757bf215546Sopenharmony_cistatic inline uint32_t 758bf215546Sopenharmony_ciutil_unsigned_fixed(float value, unsigned frac_bits) 759bf215546Sopenharmony_ci{ 760bf215546Sopenharmony_ci return value < 0 ? 0 : (uint32_t)(value * (1<<frac_bits)); 761bf215546Sopenharmony_ci} 762bf215546Sopenharmony_ci 763bf215546Sopenharmony_cistatic inline int32_t 764bf215546Sopenharmony_ciutil_signed_fixed(float value, unsigned frac_bits) 765bf215546Sopenharmony_ci{ 766bf215546Sopenharmony_ci return (int32_t)(value * (1<<frac_bits)); 767bf215546Sopenharmony_ci} 768bf215546Sopenharmony_ci 769bf215546Sopenharmony_ciunsigned 770bf215546Sopenharmony_ciutil_fpstate_get(void); 771bf215546Sopenharmony_ciunsigned 772bf215546Sopenharmony_ciutil_fpstate_set_denorms_to_zero(unsigned current_fpstate); 773bf215546Sopenharmony_civoid 774bf215546Sopenharmony_ciutil_fpstate_set(unsigned fpstate); 775bf215546Sopenharmony_ci 776bf215546Sopenharmony_ci/** 777bf215546Sopenharmony_ci * For indexed draw calls, return true if the vertex count to be drawn is 778bf215546Sopenharmony_ci * much lower than the vertex count that has to be uploaded, meaning 779bf215546Sopenharmony_ci * that the driver should flatten indices instead of trying to upload 780bf215546Sopenharmony_ci * a too big range. 781bf215546Sopenharmony_ci * 782bf215546Sopenharmony_ci * This is used by vertex upload code in u_vbuf and glthread. 783bf215546Sopenharmony_ci */ 784bf215546Sopenharmony_cistatic inline bool 785bf215546Sopenharmony_ciutil_is_vbo_upload_ratio_too_large(unsigned draw_vertex_count, 786bf215546Sopenharmony_ci unsigned upload_vertex_count) 787bf215546Sopenharmony_ci{ 788bf215546Sopenharmony_ci if (draw_vertex_count > 1024) 789bf215546Sopenharmony_ci return upload_vertex_count > draw_vertex_count * 4; 790bf215546Sopenharmony_ci else if (draw_vertex_count > 32) 791bf215546Sopenharmony_ci return upload_vertex_count > draw_vertex_count * 8; 792bf215546Sopenharmony_ci else 793bf215546Sopenharmony_ci return upload_vertex_count > draw_vertex_count * 16; 794bf215546Sopenharmony_ci} 795bf215546Sopenharmony_ci 796bf215546Sopenharmony_cibool util_invert_mat4x4(float *out, const float *m); 797bf215546Sopenharmony_ci 798bf215546Sopenharmony_ci/* Quantize the lod bias value to reduce the number of sampler state 799bf215546Sopenharmony_ci * variants in gallium because apps use it for smooth mipmap transitions, 800bf215546Sopenharmony_ci * thrashing cso_cache and degrading performance. 801bf215546Sopenharmony_ci * 802bf215546Sopenharmony_ci * This quantization matches the AMD hw specification, so having more 803bf215546Sopenharmony_ci * precision would have no effect anyway. 804bf215546Sopenharmony_ci */ 805bf215546Sopenharmony_cistatic inline float 806bf215546Sopenharmony_ciutil_quantize_lod_bias(float lod) 807bf215546Sopenharmony_ci{ 808bf215546Sopenharmony_ci lod = CLAMP(lod, -16, 16); 809bf215546Sopenharmony_ci return roundf(lod * 256) / 256; 810bf215546Sopenharmony_ci} 811bf215546Sopenharmony_ci 812bf215546Sopenharmony_ci#ifdef __cplusplus 813bf215546Sopenharmony_ci} 814bf215546Sopenharmony_ci#endif 815bf215546Sopenharmony_ci 816bf215546Sopenharmony_ci#endif /* U_MATH_H */ 817