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