Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
5564 | serge | 1 | /* |
2 | * Mesa 3-D graphics library |
||
3 | * |
||
4 | * Copyright (C) 1999-2008 Brian Paul All Rights Reserved. |
||
5 | * |
||
6 | * Permission is hereby granted, free of charge, to any person obtaining a |
||
7 | * copy of this software and associated documentation files (the "Software"), |
||
8 | * to deal in the Software without restriction, including without limitation |
||
9 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
||
10 | * and/or sell copies of the Software, and to permit persons to whom the |
||
11 | * Software is furnished to do so, subject to the following conditions: |
||
12 | * |
||
13 | * The above copyright notice and this permission notice shall be included |
||
14 | * in all copies or substantial portions of the Software. |
||
15 | * |
||
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS |
||
17 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
||
19 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR |
||
20 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, |
||
21 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR |
||
22 | * OTHER DEALINGS IN THE SOFTWARE. |
||
23 | */ |
||
24 | |||
25 | |||
26 | /** |
||
27 | * \file imports.h |
||
28 | * Standard C library function wrappers. |
||
29 | * |
||
30 | * This file provides wrappers for all the standard C library functions |
||
31 | * like malloc(), free(), printf(), getenv(), etc. |
||
32 | */ |
||
33 | |||
34 | |||
35 | #ifndef IMPORTS_H |
||
36 | #define IMPORTS_H |
||
37 | |||
38 | |||
39 | #include |
||
40 | #include |
||
41 | #include |
||
42 | #include "compiler.h" |
||
43 | #include "glheader.h" |
||
44 | #include "errors.h" |
||
45 | |||
46 | #ifdef __cplusplus |
||
47 | extern "C" { |
||
48 | #endif |
||
49 | |||
50 | |||
51 | /**********************************************************************/ |
||
52 | /** Memory macros */ |
||
53 | /*@{*/ |
||
54 | |||
55 | /** Allocate a structure of type \p T */ |
||
56 | #define MALLOC_STRUCT(T) (struct T *) malloc(sizeof(struct T)) |
||
57 | /** Allocate and zero a structure of type \p T */ |
||
58 | #define CALLOC_STRUCT(T) (struct T *) calloc(1, sizeof(struct T)) |
||
59 | |||
60 | /*@}*/ |
||
61 | |||
62 | |||
63 | /* |
||
64 | * For GL_ARB_vertex_buffer_object we need to treat vertex array pointers |
||
65 | * as offsets into buffer stores. Since the vertex array pointer and |
||
66 | * buffer store pointer are both pointers and we need to add them, we use |
||
67 | * this macro. |
||
68 | * Both pointers/offsets are expressed in bytes. |
||
69 | */ |
||
70 | #define ADD_POINTERS(A, B) ( (GLubyte *) (A) + (uintptr_t) (B) ) |
||
71 | |||
72 | |||
73 | /** |
||
74 | * Sometimes we treat GLfloats as GLints. On x86 systems, moving a float |
||
75 | * as a int (thereby using integer registers instead of FP registers) is |
||
76 | * a performance win. Typically, this can be done with ordinary casts. |
||
77 | * But with gcc's -fstrict-aliasing flag (which defaults to on in gcc 3.0) |
||
78 | * these casts generate warnings. |
||
79 | * The following union typedef is used to solve that. |
||
80 | */ |
||
81 | typedef union { GLfloat f; GLint i; GLuint u; } fi_type; |
||
82 | |||
83 | |||
84 | |||
85 | #if defined(_MSC_VER) |
||
86 | #if _MSC_VER < 1800 /* Not req'd on VS2013 and above */ |
||
87 | #define strtoll(p, e, b) _strtoi64(p, e, b) |
||
88 | #endif /* _MSC_VER < 1800 */ |
||
89 | #define strcasecmp(s1, s2) _stricmp(s1, s2) |
||
90 | #endif |
||
91 | /*@}*/ |
||
92 | |||
93 | |||
94 | /*** |
||
95 | *** LOG2: Log base 2 of float |
||
96 | ***/ |
||
97 | static inline GLfloat LOG2(GLfloat x) |
||
98 | { |
||
99 | #if 0 |
||
100 | /* This is pretty fast, but not accurate enough (only 2 fractional bits). |
||
101 | * Based on code from http://www.stereopsis.com/log2.html |
||
102 | */ |
||
103 | const GLfloat y = x * x * x * x; |
||
104 | const GLuint ix = *((GLuint *) &y); |
||
105 | const GLuint exp = (ix >> 23) & 0xFF; |
||
106 | const GLint log2 = ((GLint) exp) - 127; |
||
107 | return (GLfloat) log2 * (1.0 / 4.0); /* 4, because of x^4 above */ |
||
108 | #endif |
||
109 | /* Pretty fast, and accurate. |
||
110 | * Based on code from http://www.flipcode.com/totd/ |
||
111 | */ |
||
112 | fi_type num; |
||
113 | GLint log_2; |
||
114 | num.f = x; |
||
115 | log_2 = ((num.i >> 23) & 255) - 128; |
||
116 | num.i &= ~(255 << 23); |
||
117 | num.i += 127 << 23; |
||
118 | num.f = ((-1.0f/3) * num.f + 2) * num.f - 2.0f/3; |
||
119 | return num.f + log_2; |
||
120 | } |
||
121 | |||
122 | |||
123 | |||
124 | /** |
||
125 | * finite macro. |
||
126 | */ |
||
127 | #if defined(_MSC_VER) |
||
128 | # define finite _finite |
||
129 | #endif |
||
130 | |||
131 | |||
132 | /*** |
||
133 | *** IS_INF_OR_NAN: test if float is infinite or NaN |
||
134 | ***/ |
||
135 | #if defined(isfinite) |
||
136 | #define IS_INF_OR_NAN(x) (!isfinite(x)) |
||
137 | #elif defined(finite) |
||
138 | #define IS_INF_OR_NAN(x) (!finite(x)) |
||
139 | #elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L |
||
140 | #define IS_INF_OR_NAN(x) (!isfinite(x)) |
||
141 | #else |
||
142 | #define IS_INF_OR_NAN(x) (!finite(x)) |
||
143 | #endif |
||
144 | |||
145 | |||
146 | /** |
||
147 | * Convert float to int by rounding to nearest integer, away from zero. |
||
148 | */ |
||
149 | static inline int IROUND(float f) |
||
150 | { |
||
151 | return (int) ((f >= 0.0F) ? (f + 0.5F) : (f - 0.5F)); |
||
152 | } |
||
153 | |||
154 | |||
155 | /** |
||
156 | * Convert float to int64 by rounding to nearest integer. |
||
157 | */ |
||
158 | static inline GLint64 IROUND64(float f) |
||
159 | { |
||
160 | return (GLint64) ((f >= 0.0F) ? (f + 0.5F) : (f - 0.5F)); |
||
161 | } |
||
162 | |||
163 | |||
164 | /** |
||
165 | * Convert positive float to int by rounding to nearest integer. |
||
166 | */ |
||
167 | static inline int IROUND_POS(float f) |
||
168 | { |
||
169 | assert(f >= 0.0F); |
||
170 | return (int) (f + 0.5F); |
||
171 | } |
||
172 | |||
173 | #ifdef __x86_64__ |
||
174 | # include |
||
175 | #endif |
||
176 | |||
177 | /** |
||
178 | * Convert float to int using a fast method. The rounding mode may vary. |
||
179 | */ |
||
180 | static inline int F_TO_I(float f) |
||
181 | { |
||
182 | #if defined(USE_X86_ASM) && defined(__GNUC__) && defined(__i386__) |
||
183 | int r; |
||
184 | __asm__ ("fistpl %0" : "=m" (r) : "t" (f) : "st"); |
||
185 | return r; |
||
186 | #elif defined(USE_X86_ASM) && defined(_MSC_VER) |
||
187 | int r; |
||
188 | _asm { |
||
189 | fld f |
||
190 | fistp r |
||
191 | } |
||
192 | return r; |
||
193 | #elif defined(__x86_64__) |
||
194 | return _mm_cvt_ss2si(_mm_load_ss(&f)); |
||
195 | #else |
||
196 | return IROUND(f); |
||
197 | #endif |
||
198 | } |
||
199 | |||
200 | |||
201 | /** Return (as an integer) floor of float */ |
||
202 | static inline int IFLOOR(float f) |
||
203 | { |
||
204 | #if defined(USE_X86_ASM) && defined(__GNUC__) && defined(__i386__) |
||
205 | /* |
||
206 | * IEEE floor for computers that round to nearest or even. |
||
207 | * 'f' must be between -4194304 and 4194303. |
||
208 | * This floor operation is done by "(iround(f + .5) + iround(f - .5)) >> 1", |
||
209 | * but uses some IEEE specific tricks for better speed. |
||
210 | * Contributed by Josh Vanderhoof |
||
211 | */ |
||
212 | int ai, bi; |
||
213 | double af, bf; |
||
214 | af = (3 << 22) + 0.5 + (double)f; |
||
215 | bf = (3 << 22) + 0.5 - (double)f; |
||
216 | /* GCC generates an extra fstp/fld without this. */ |
||
217 | __asm__ ("fstps %0" : "=m" (ai) : "t" (af) : "st"); |
||
218 | __asm__ ("fstps %0" : "=m" (bi) : "t" (bf) : "st"); |
||
219 | return (ai - bi) >> 1; |
||
220 | #else |
||
221 | int ai, bi; |
||
222 | double af, bf; |
||
223 | fi_type u; |
||
224 | af = (3 << 22) + 0.5 + (double)f; |
||
225 | bf = (3 << 22) + 0.5 - (double)f; |
||
226 | u.f = (float) af; ai = u.i; |
||
227 | u.f = (float) bf; bi = u.i; |
||
228 | return (ai - bi) >> 1; |
||
229 | #endif |
||
230 | } |
||
231 | |||
232 | |||
233 | /** Return (as an integer) ceiling of float */ |
||
234 | static inline int ICEIL(float f) |
||
235 | { |
||
236 | #if defined(USE_X86_ASM) && defined(__GNUC__) && defined(__i386__) |
||
237 | /* |
||
238 | * IEEE ceil for computers that round to nearest or even. |
||
239 | * 'f' must be between -4194304 and 4194303. |
||
240 | * This ceil operation is done by "(iround(f + .5) + iround(f - .5) + 1) >> 1", |
||
241 | * but uses some IEEE specific tricks for better speed. |
||
242 | * Contributed by Josh Vanderhoof |
||
243 | */ |
||
244 | int ai, bi; |
||
245 | double af, bf; |
||
246 | af = (3 << 22) + 0.5 + (double)f; |
||
247 | bf = (3 << 22) + 0.5 - (double)f; |
||
248 | /* GCC generates an extra fstp/fld without this. */ |
||
249 | __asm__ ("fstps %0" : "=m" (ai) : "t" (af) : "st"); |
||
250 | __asm__ ("fstps %0" : "=m" (bi) : "t" (bf) : "st"); |
||
251 | return (ai - bi + 1) >> 1; |
||
252 | #else |
||
253 | int ai, bi; |
||
254 | double af, bf; |
||
255 | fi_type u; |
||
256 | af = (3 << 22) + 0.5 + (double)f; |
||
257 | bf = (3 << 22) + 0.5 - (double)f; |
||
258 | u.f = (float) af; ai = u.i; |
||
259 | u.f = (float) bf; bi = u.i; |
||
260 | return (ai - bi + 1) >> 1; |
||
261 | #endif |
||
262 | } |
||
263 | |||
264 | |||
265 | /** |
||
266 | * Is x a power of two? |
||
267 | */ |
||
268 | static inline int |
||
269 | _mesa_is_pow_two(int x) |
||
270 | { |
||
271 | return !(x & (x - 1)); |
||
272 | } |
||
273 | |||
274 | /** |
||
275 | * Round given integer to next higer power of two |
||
276 | * If X is zero result is undefined. |
||
277 | * |
||
278 | * Source for the fallback implementation is |
||
279 | * Sean Eron Anderson's webpage "Bit Twiddling Hacks" |
||
280 | * http://graphics.stanford.edu/~seander/bithacks.html |
||
281 | * |
||
282 | * When using builtin function have to do some work |
||
283 | * for case when passed values 1 to prevent hiting |
||
284 | * undefined result from __builtin_clz. Undefined |
||
285 | * results would be different depending on optimization |
||
286 | * level used for build. |
||
287 | */ |
||
288 | static inline int32_t |
||
289 | _mesa_next_pow_two_32(uint32_t x) |
||
290 | { |
||
291 | #ifdef HAVE___BUILTIN_CLZ |
||
292 | uint32_t y = (x != 1); |
||
293 | return (1 + y) << ((__builtin_clz(x - y) ^ 31) ); |
||
294 | #else |
||
295 | x--; |
||
296 | x |= x >> 1; |
||
297 | x |= x >> 2; |
||
298 | x |= x >> 4; |
||
299 | x |= x >> 8; |
||
300 | x |= x >> 16; |
||
301 | x++; |
||
302 | return x; |
||
303 | #endif |
||
304 | } |
||
305 | |||
306 | static inline int64_t |
||
307 | _mesa_next_pow_two_64(uint64_t x) |
||
308 | { |
||
309 | #ifdef HAVE___BUILTIN_CLZLL |
||
310 | uint64_t y = (x != 1); |
||
311 | STATIC_ASSERT(sizeof(x) == sizeof(long long)); |
||
312 | return (1 + y) << ((__builtin_clzll(x - y) ^ 63)); |
||
313 | #else |
||
314 | x--; |
||
315 | x |= x >> 1; |
||
316 | x |= x >> 2; |
||
317 | x |= x >> 4; |
||
318 | x |= x >> 8; |
||
319 | x |= x >> 16; |
||
320 | x |= x >> 32; |
||
321 | x++; |
||
322 | return x; |
||
323 | #endif |
||
324 | } |
||
325 | |||
326 | |||
327 | /* |
||
328 | * Returns the floor form of binary logarithm for a 32-bit integer. |
||
329 | */ |
||
330 | static inline GLuint |
||
331 | _mesa_logbase2(GLuint n) |
||
332 | { |
||
333 | #ifdef HAVE___BUILTIN_CLZ |
||
334 | return (31 - __builtin_clz(n | 1)); |
||
335 | #else |
||
336 | GLuint pos = 0; |
||
337 | if (n >= 1<<16) { n >>= 16; pos += 16; } |
||
338 | if (n >= 1<< 8) { n >>= 8; pos += 8; } |
||
339 | if (n >= 1<< 4) { n >>= 4; pos += 4; } |
||
340 | if (n >= 1<< 2) { n >>= 2; pos += 2; } |
||
341 | if (n >= 1<< 1) { pos += 1; } |
||
342 | return pos; |
||
343 | #endif |
||
344 | } |
||
345 | |||
346 | |||
347 | /** |
||
348 | * Return 1 if this is a little endian machine, 0 if big endian. |
||
349 | */ |
||
350 | static inline GLboolean |
||
351 | _mesa_little_endian(void) |
||
352 | { |
||
353 | const GLuint ui = 1; /* intentionally not static */ |
||
354 | return *((const GLubyte *) &ui); |
||
355 | } |
||
356 | |||
357 | |||
358 | |||
359 | /********************************************************************** |
||
360 | * Functions |
||
361 | */ |
||
362 | |||
363 | extern void * |
||
364 | _mesa_align_malloc( size_t bytes, unsigned long alignment ); |
||
365 | |||
366 | extern void * |
||
367 | _mesa_align_calloc( size_t bytes, unsigned long alignment ); |
||
368 | |||
369 | extern void |
||
370 | _mesa_align_free( void *ptr ); |
||
371 | |||
372 | extern void * |
||
373 | _mesa_align_realloc(void *oldBuffer, size_t oldSize, size_t newSize, |
||
374 | unsigned long alignment); |
||
375 | |||
376 | extern void * |
||
377 | _mesa_exec_malloc( GLuint size ); |
||
378 | |||
379 | extern void |
||
380 | _mesa_exec_free( void *addr ); |
||
381 | |||
382 | |||
383 | #ifndef FFS_DEFINED |
||
384 | #define FFS_DEFINED 1 |
||
385 | #ifdef HAVE___BUILTIN_FFS |
||
386 | #define ffs __builtin_ffs |
||
387 | #else |
||
388 | extern int ffs(int i); |
||
389 | #endif |
||
390 | |||
391 | #ifdef HAVE___BUILTIN_FFSLL |
||
392 | #define ffsll __builtin_ffsll |
||
393 | #else |
||
394 | extern int ffsll(long long int i); |
||
395 | #endif |
||
396 | #endif /* FFS_DEFINED */ |
||
397 | |||
398 | |||
399 | #ifdef HAVE___BUILTIN_POPCOUNT |
||
400 | #define _mesa_bitcount(i) __builtin_popcount(i) |
||
401 | #else |
||
402 | extern unsigned int |
||
403 | _mesa_bitcount(unsigned int n); |
||
404 | #endif |
||
405 | |||
406 | #ifdef HAVE___BUILTIN_POPCOUNTLL |
||
407 | #define _mesa_bitcount_64(i) __builtin_popcountll(i) |
||
408 | #else |
||
409 | extern unsigned int |
||
410 | _mesa_bitcount_64(uint64_t n); |
||
411 | #endif |
||
412 | |||
413 | /** |
||
414 | * Find the last (most significant) bit set in a word. |
||
415 | * |
||
416 | * Essentially ffs() in the reverse direction. |
||
417 | */ |
||
418 | static inline unsigned int |
||
419 | _mesa_fls(unsigned int n) |
||
420 | { |
||
421 | #ifdef HAVE___BUILTIN_CLZ |
||
422 | return n == 0 ? 0 : 32 - __builtin_clz(n); |
||
423 | #else |
||
424 | unsigned int v = 1; |
||
425 | |||
426 | if (n == 0) |
||
427 | return 0; |
||
428 | |||
429 | while (n >>= 1) |
||
430 | v++; |
||
431 | |||
432 | return v; |
||
433 | #endif |
||
434 | } |
||
435 | |||
436 | /** |
||
437 | * Find the last (most significant) bit set in a uint64_t value. |
||
438 | * |
||
439 | * Essentially ffsll() in the reverse direction. |
||
440 | */ |
||
441 | static inline unsigned int |
||
442 | _mesa_flsll(uint64_t n) |
||
443 | { |
||
444 | #ifdef HAVE___BUILTIN_CLZLL |
||
445 | return n == 0 ? 0 : 64 - __builtin_clzll(n); |
||
446 | #else |
||
447 | unsigned int v = 1; |
||
448 | |||
449 | if (n == 0) |
||
450 | return 0; |
||
451 | |||
452 | while (n >>= 1) |
||
453 | v++; |
||
454 | |||
455 | return v; |
||
456 | #endif |
||
457 | } |
||
458 | |||
459 | |||
460 | extern GLhalfARB |
||
461 | _mesa_float_to_half(float f); |
||
462 | |||
463 | extern float |
||
464 | _mesa_half_to_float(GLhalfARB h); |
||
465 | |||
466 | static inline bool |
||
467 | _mesa_half_is_negative(GLhalfARB h) |
||
468 | { |
||
469 | return h & 0x8000; |
||
470 | } |
||
471 | |||
472 | extern unsigned int |
||
473 | _mesa_str_checksum(const char *str); |
||
474 | |||
475 | extern int |
||
476 | _mesa_snprintf( char *str, size_t size, const char *fmt, ... ) PRINTFLIKE(3, 4); |
||
477 | |||
478 | extern int |
||
479 | _mesa_vsnprintf(char *str, size_t size, const char *fmt, va_list arg); |
||
480 | |||
481 | |||
482 | #if defined(_MSC_VER) && !defined(snprintf) |
||
483 | #define snprintf _snprintf |
||
484 | #endif |
||
485 | |||
486 | |||
487 | #ifdef __cplusplus |
||
488 | } |
||
489 | #endif |
||
490 | |||
491 | |||
492 | #endif /* IMPORTS_H */><>><>><>><>16)><16)>><>><>><>><>><>><>><>><>><>><>><>><>>> |