]> git.cworth.org Git - vogl/blob - src/voglcore/vogl_utils.h
Initial vogl checkin
[vogl] / src / voglcore / vogl_utils.h
1 /**************************************************************************
2  *
3  * Copyright 2013-2014 RAD Game Tools and Valve Software
4  * Copyright 2010-2014 Rich Geldreich and Tenacious Software LLC
5  * All Rights Reserved.
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining a copy
8  * of this software and associated documentation files (the "Software"), to deal
9  * in the Software without restriction, including without limitation the rights
10  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11  * copies of the Software, and to permit persons to whom the Software is
12  * furnished to do so, subject to the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be included in
15  * all copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23  * THE SOFTWARE.
24  *
25  **************************************************************************/
26
27 // File: vogl_utils.h
28 #pragma once
29
30 #if defined(VOGL_USE_LINUX_API)
31 #include <time.h>
32 #endif
33 #include "vogl_core.h"
34
35 #define VOGL_OFFSETOF(t, e) ((uint32)(intptr_t)(&((t *)(0))->e))
36
37 #define VOGL_MIN(a, b) (((a) < (b)) ? (a) : (b))
38 #define VOGL_MAX(a, b) (((a) < (b)) ? (b) : (a))
39
40 #define VOGL_GLUER(a, b) a##b
41
42 #ifdef _MSC_VER
43 // Need to explictly extern these with MSVC, but not MinGW.
44 extern "C" unsigned long __cdecl _lrotl(unsigned long, int);
45 #pragma intrinsic(_lrotl)
46
47 extern "C" unsigned long __cdecl _lrotr(unsigned long, int);
48 #pragma intrinsic(_lrotr)
49 #endif
50
51 #ifdef WIN32
52 #define VOGL_ROTATE_LEFT(x, k) _lrotl(x, k)
53 #define VOGL_ROTATE_RIGHT(x, k) _lrotr(x, k)
54 #else
55 #define VOGL_ROTATE_LEFT(x, k) (((x) << (k)) | ((x) >> (32 - (k))))
56 #define VOGL_ROTATE_RIGHT(x, k) (((x) >> (k)) | ((x) << (32 - (k))))
57 #endif
58
59 template <class T, size_t N>
60 T decay_array_to_subtype(T (&a)[N]);
61 #define VOGL_ARRAY_SIZE(X) (sizeof(X) / sizeof(decay_array_to_subtype(X)))
62
63 #define VOGL_SIZEOF_U32(x) static_cast<uint32>(sizeof(x))
64
65 // Returns # of bits needed to encode x, i.e. 0=0, 1=1, 0xFFFF=15, 0x10000=16, etc.
66 #define VOGL_SIGNIFICANT_BITS(x)                                                               \
67     (!!((x) & 0x80000000) + !!((x) & 0xc0000000) + !!((x) & 0xe0000000) + !!((x) & 0xf0000000) + \
68      !!((x) & 0xf8000000) + !!((x) & 0xfc000000) + !!((x) & 0xfe000000) + !!((x) & 0xff000000) + \
69      !!((x) & 0xff800000) + !!((x) & 0xffc00000) + !!((x) & 0xffe00000) + !!((x) & 0xfff00000) + \
70      !!((x) & 0xfff80000) + !!((x) & 0xfffc0000) + !!((x) & 0xfffe0000) + !!((x) & 0xffff0000) + \
71      !!((x) & 0xffff8000) + !!((x) & 0xffffc000) + !!((x) & 0xffffe000) + !!((x) & 0xfffff000) + \
72      !!((x) & 0xfffff800) + !!((x) & 0xfffffc00) + !!((x) & 0xfffffe00) + !!((x) & 0xffffff00) + \
73      !!((x) & 0xffffff80) + !!((x) & 0xffffffc0) + !!((x) & 0xffffffe0) + !!((x) & 0xfffffff0) + \
74      !!((x) & 0xfffffff8) + !!((x) & 0xfffffffc) + !!((x) & 0xfffffffe) + !!((x) & 0xffffffff))
75
76 #define VOGL_HAS_NULLBYTE(x) (((x) - 0x01010101) & ~(x) & 0x80808080)
77
78 namespace vogl
79 {
80     namespace utils
81     {
82         template <typename T>
83         struct relative_ops
84         {
85             friend bool operator>(const T &a, const T &b)
86             {
87                 return b < a;
88             }
89             friend bool operator<=(const T &a, const T &b)
90             {
91                 return !(b < a);
92             }
93             friend bool operator>=(const T &a, const T &b)
94             {
95                 return !(a < b);
96             }
97             friend bool operator!=(const T &a, const T &b)
98             {
99                 return !(a == b);
100             }
101         };
102
103         // Given a less than comparison functor comp, compare a and b
104         template <typename T, typename F>
105         bool compare_lt(const T &a, const T &b, F comp)
106         {
107             return comp(a, b);
108         }
109         template <typename T, typename F>
110         bool compare_le(const T &a, const T &b, F comp)
111         {
112             return !comp(b, a);
113         }
114         template <typename T, typename F>
115         bool compare_gt(const T &a, const T &b, F comp)
116         {
117             return comp(b, a);
118         }
119         template <typename T, typename F>
120         bool compare_ge(const T &a, const T &b, F comp)
121         {
122             return !comp(a, b);
123         }
124         template <typename T, typename F>
125         bool compare_eq(const T &a, const T &b, F comp)
126         {
127             return !comp(a, b) && !comp(b, a);
128         }
129         template <typename T, typename F>
130         bool compare_neq(const T &a, const T &b, F comp)
131         {
132             return comp(a, b) || comp(b, a);
133         }
134
135         template <typename T>
136         inline void swap(T &l, T &r)
137         {
138             // Using std::swap() here now because it has C++0x optimizations and it can swap C-style arrays.
139             std::swap(l, r);
140         }
141
142         template <typename T>
143         inline void zero_object(T &obj)
144         {
145             memset((void *)&obj, 0, sizeof(obj));
146         }
147
148         template <typename T>
149         inline void zero_this(T *pObj)
150         {
151             memset((void *)pObj, 0, sizeof(*pObj));
152         }
153
154         inline bool is_bit_set(uint bits, uint mask)
155         {
156             return (bits & mask) != 0;
157         }
158
159         inline void set_bit(uint &bits, uint mask, bool state)
160         {
161             if (state)
162                 bits |= mask;
163             else
164                 bits &= ~mask;
165         }
166
167         inline bool is_flag_set(uint bits, uint flag)
168         {
169             VOGL_ASSERT(flag < 32U);
170             return is_bit_set(bits, 1U << flag);
171         }
172
173         inline void set_flag(uint &bits, uint flag, bool state)
174         {
175             VOGL_ASSERT(flag < 32U);
176             set_bit(bits, 1U << flag, state);
177         }
178
179         inline void invert_buf(void *pBuf, uint size)
180         {
181             uint8 *p = static_cast<uint8 *>(pBuf);
182
183             const uint half_size = size >> 1;
184             for (uint i = 0; i < half_size; i++)
185                 utils::swap(p[i], p[size - 1U - i]);
186         }
187
188         // buffer_is_little_endian is the endianness of the buffer's data
189         template <typename T>
190         inline void write_obj(const T &obj, void *pBuf, bool buffer_is_little_endian)
191         {
192             const uint8 *pSrc = reinterpret_cast<const uint8 *>(&obj);
193             uint8 *pDst = static_cast<uint8 *>(pBuf);
194
195             if (c_vogl_little_endian_platform == buffer_is_little_endian)
196                 memcpy(pDst, pSrc, sizeof(T));
197             else
198             {
199                 for (uint i = 0; i < sizeof(T); i++)
200                     pDst[i] = pSrc[sizeof(T) - 1 - i];
201             }
202         }
203
204         // buffer_is_little_endian is the endianness of the buffer's data
205         template <typename T>
206         inline void read_obj(T &obj, const void *pBuf, bool buffer_is_little_endian)
207         {
208             const uint8 *pSrc = reinterpret_cast<const uint8 *>(pBuf);
209             uint8 *pDst = reinterpret_cast<uint8 *>(&obj);
210
211             if (c_vogl_little_endian_platform == buffer_is_little_endian)
212                 memcpy(pDst, pSrc, sizeof(T));
213             else
214             {
215                 for (uint i = 0; i < sizeof(T); i++)
216                     pDst[i] = pSrc[sizeof(T) - 1 - i];
217             }
218         }
219
220         template <typename T>
221         inline bool write_obj(const T &obj, void *&pBuf, uint &buf_size, bool buffer_is_little_endian)
222         {
223             if (buf_size < sizeof(T))
224                 return false;
225
226             utils::write_obj(obj, pBuf, buffer_is_little_endian);
227
228             pBuf = static_cast<uint8 *>(pBuf) + sizeof(T);
229             buf_size -= sizeof(T);
230
231             return true;
232         }
233
234         inline bool write_val(uint8 val, void *&pBuf, uint &buf_size, bool buffer_is_little_endian)
235         {
236             return write_obj(val, pBuf, buf_size, buffer_is_little_endian);
237         }
238         inline bool write_val(uint16 val, void *&pBuf, uint &buf_size, bool buffer_is_little_endian)
239         {
240             return write_obj(val, pBuf, buf_size, buffer_is_little_endian);
241         }
242         inline bool write_val(uint val, void *&pBuf, uint &buf_size, bool buffer_is_little_endian)
243         {
244             return write_obj(val, pBuf, buf_size, buffer_is_little_endian);
245         }
246         inline bool write_val(int val, void *&pBuf, uint &buf_size, bool buffer_is_little_endian)
247         {
248             return write_obj(val, pBuf, buf_size, buffer_is_little_endian);
249         }
250         inline bool write_val(uint64_t val, void *&pBuf, uint &buf_size, bool buffer_is_little_endian)
251         {
252             return write_obj(val, pBuf, buf_size, buffer_is_little_endian);
253         }
254         inline bool write_val(float val, void *&pBuf, uint &buf_size, bool buffer_is_little_endian)
255         {
256             return write_obj(val, pBuf, buf_size, buffer_is_little_endian);
257         }
258         inline bool write_val(double val, void *&pBuf, uint &buf_size, bool buffer_is_little_endian)
259         {
260             return write_obj(val, pBuf, buf_size, buffer_is_little_endian);
261         }
262
263         template <typename T>
264         inline bool read_obj(T &obj, const void *&pBuf, uint &buf_size, bool buffer_is_little_endian)
265         {
266             if (buf_size < sizeof(T))
267             {
268                 zero_object(obj);
269                 return false;
270             }
271
272             utils::read_obj(obj, pBuf, buffer_is_little_endian);
273
274             pBuf = static_cast<const uint8 *>(pBuf) + sizeof(T);
275             buf_size -= sizeof(T);
276
277             return true;
278         }
279
280 #if defined(_MSC_VER)
281         VOGL_FORCE_INLINE uint16 swap16(uint16 x)
282         {
283             return _byteswap_ushort(x);
284         }
285         VOGL_FORCE_INLINE uint32 swap32(uint32 x)
286         {
287             return _byteswap_ulong(x);
288         }
289         VOGL_FORCE_INLINE uint64_t swap64(uint64_t x)
290         {
291             return _byteswap_uint64(x);
292         }
293 #elif defined(__GNUC__)
294         VOGL_FORCE_INLINE uint16 swap16(uint16 x)
295         {
296             return static_cast<uint16>((x << 8U) | (x >> 8U));
297         }
298         VOGL_FORCE_INLINE uint32 swap32(uint32 x)
299         {
300             return __builtin_bswap32(x);
301         }
302         VOGL_FORCE_INLINE uint64_t swap64(uint64_t x)
303         {
304             return __builtin_bswap64(x);
305         }
306 #else
307         VOGL_FORCE_INLINE uint16 swap16(uint16 x)
308         {
309             return static_cast<uint16>((x << 8U) | (x >> 8U));
310         }
311         VOGL_FORCE_INLINE uint32 swap32(uint32 x)
312         {
313             return ((x << 24U) | ((x << 8U) & 0x00FF0000U) | ((x >> 8U) & 0x0000FF00U) | (x >> 24U));
314         }
315         VOGL_FORCE_INLINE uint64_t swap64(uint64_t x)
316         {
317             return (static_cast<uint64_t>(swap32(static_cast<uint32>(x))) << 32ULL) | swap32(static_cast<uint32>(x >> 32U));
318         }
319 #endif
320
321         // Assumes x has been read from memory as a little endian value, converts to native endianness for manipulation.
322         VOGL_FORCE_INLINE uint16 swap_le16_to_native(uint16 x)
323         {
324             return c_vogl_little_endian_platform ? x : swap16(x);
325         }
326         VOGL_FORCE_INLINE uint32 swap_le32_to_native(uint32 x)
327         {
328             return c_vogl_little_endian_platform ? x : swap32(x);
329         }
330         VOGL_FORCE_INLINE uint64_t swap_le64_to_native(uint64_t x)
331         {
332             return c_vogl_little_endian_platform ? x : swap64(x);
333         }
334
335         // Assumes x has been read from memory as a big endian value, converts to native endianness for manipulation.
336         VOGL_FORCE_INLINE uint16 swap_be16_to_native(uint16 x)
337         {
338             return c_vogl_big_endian_platform ? x : swap16(x);
339         }
340         VOGL_FORCE_INLINE uint32 swap_be32_to_native(uint32 x)
341         {
342             return c_vogl_big_endian_platform ? x : swap32(x);
343         }
344         VOGL_FORCE_INLINE uint64_t swap_be64_to_native(uint64_t x)
345         {
346             return c_vogl_big_endian_platform ? x : swap64(x);
347         }
348
349         VOGL_FORCE_INLINE uint32 read_le32(const void *p)
350         {
351             return swap_le32_to_native(*static_cast<const uint32 *>(p));
352         }
353         VOGL_FORCE_INLINE void write_le32(void *p, uint32 x)
354         {
355             *static_cast<uint32 *>(p) = swap_le32_to_native(x);
356         }
357         VOGL_FORCE_INLINE uint64_t read_le64(const void *p)
358         {
359             return swap_le64_to_native(*static_cast<const uint64_t *>(p));
360         }
361         VOGL_FORCE_INLINE void write_le64(void *p, uint64_t x)
362         {
363             *static_cast<uint64_t *>(p) = swap_le64_to_native(x);
364         }
365
366         VOGL_FORCE_INLINE uint32 read_be32(const void *p)
367         {
368             return swap_be32_to_native(*static_cast<const uint32 *>(p));
369         }
370         VOGL_FORCE_INLINE void write_be32(void *p, uint32 x)
371         {
372             *static_cast<uint32 *>(p) = swap_be32_to_native(x);
373         }
374         VOGL_FORCE_INLINE uint64_t read_be64(const void *p)
375         {
376             return swap_be64_to_native(*static_cast<const uint64_t *>(p));
377         }
378         VOGL_FORCE_INLINE void write_be64(void *p, uint64_t x)
379         {
380             *static_cast<uint64_t *>(p) = swap_be64_to_native(x);
381         }
382
383         inline void endian_swap_mem16(uint16 *p, uint n)
384         {
385             while (n--)
386             {
387                 *p = swap16(*p);
388                 ++p;
389             }
390         }
391         inline void endian_swap_mem32(uint32 *p, uint n)
392         {
393             while (n--)
394             {
395                 *p = swap32(*p);
396                 ++p;
397             }
398         }
399         inline void endian_swap_mem64(uint64_t *p, uint n)
400         {
401             while (n--)
402             {
403                 *p = swap64(*p);
404                 ++p;
405             }
406         }
407
408         inline void endian_swap_mem(void *p, uint size_in_bytes, uint type_size)
409         {
410             switch (type_size)
411             {
412                 case sizeof(uint16)
413                     :
414                     endian_swap_mem16(static_cast<uint16 *>(p), size_in_bytes / type_size);
415                     break;
416                 case sizeof(uint32)
417                     :
418                     endian_swap_mem32(static_cast<uint32 *>(p), size_in_bytes / type_size);
419                     break;
420                 case sizeof(uint64_t)
421                     :
422                     endian_swap_mem64(static_cast<uint64_t *>(p), size_in_bytes / type_size);
423                     break;
424             }
425         }
426
427         inline void fast_memset(void *pDst, int val, size_t size)
428         {
429             memset(pDst, val, size);
430         }
431
432         inline void fast_memcpy(void *pDst, const void *pSrc, size_t size)
433         {
434             memcpy(pDst, pSrc, size);
435         }
436
437         inline uint count_leading_zeros(uint v)
438         {
439             uint temp;
440             uint n = 32;
441
442             temp = v >> 16;
443             if (temp)
444             {
445                 n -= 16;
446                 v = temp;
447             }
448
449             temp = v >> 8;
450             if (temp)
451             {
452                 n -= 8;
453                 v = temp;
454             }
455
456             temp = v >> 4;
457             if (temp)
458             {
459                 n -= 4;
460                 v = temp;
461             }
462
463             temp = v >> 2;
464             if (temp)
465             {
466                 n -= 2;
467                 v = temp;
468             }
469
470             temp = v >> 1;
471             if (temp)
472             {
473                 n -= 1;
474                 v = temp;
475             }
476
477             if (v & 1)
478                 n--;
479
480             return n;
481         }
482
483         inline uint count_leading_zeros16(uint v)
484         {
485             VOGL_ASSERT(v < 0x10000);
486
487             uint temp;
488             uint n = 16;
489
490             temp = v >> 8;
491             if (temp)
492             {
493                 n -= 8;
494                 v = temp;
495             }
496
497             temp = v >> 4;
498             if (temp)
499             {
500                 n -= 4;
501                 v = temp;
502             }
503
504             temp = v >> 2;
505             if (temp)
506             {
507                 n -= 2;
508                 v = temp;
509             }
510
511             temp = v >> 1;
512             if (temp)
513             {
514                 n -= 1;
515                 v = temp;
516             }
517
518             if (v & 1)
519                 n--;
520
521             return n;
522         }
523
524         void endian_switch_words(uint16 *p, uint num);
525         void endian_switch_dwords(uint32 *p, uint num);
526         void copy_words(uint16 *pDst, const uint16 *pSrc, uint num, bool endian_switch);
527         void copy_dwords(uint32 *pDst, const uint32 *pSrc, uint num, bool endian_switch);
528
529         // Returns the maximum number of mip levels given the specified width/height, including the first (largest) mip level.
530         uint compute_max_mips(uint width, uint height, uint min_width = 1U, uint min_height = 1U);
531         uint compute_max_mips3D(uint width, uint height, uint depth, uint min_width = 1U, uint min_height = 1U, uint min_depth = 1U);
532
533         bool check_for_sse_4_1_support();
534
535         inline char to_hex(uint v)
536         {
537             VOGL_ASSERT(v <= 0xF);
538             if (v < 10)
539                 return '0' + v;
540             else if (v <= 0xF)
541                 return 'A' + v - 10;
542             return 0;
543         }
544
545         inline int from_hex(char c)
546         {
547             if ((c >= '0') && (c <= '9'))
548                 return c - '0';
549             else if ((c >= 'a') && (c <= 'f'))
550                 return (c - 'a') + 10;
551             else if ((c >= 'A') && (c <= 'F'))
552                 return (c - 'A') + 10;
553             return -1;
554         }
555
556         bool is_buffer_printable(const void *pBuf, uint buf_size, bool include_crlf, bool expect_null_terminator);
557
558         extern const int64_t s_signed_mins[9];
559         extern const int64_t s_signed_maxs[9];
560         extern const uint64_t s_unsigned_maxes[9];
561
562         inline int64_t get_signed_min_value(uint integral_type_size)
563         {
564             VOGL_ASSERT(integral_type_size <= 8);
565             int64_t val = (integral_type_size <= 8) ? s_signed_mins[integral_type_size] : 0;
566             VOGL_ASSERT((!integral_type_size) || (val == (-s_signed_maxs[integral_type_size] - 1)));
567             return val;
568         }
569
570         inline int64_t get_signed_max_value(uint integral_type_size)
571         {
572             VOGL_ASSERT(integral_type_size <= 8);
573             int64_t val = (integral_type_size <= 8) ? s_signed_maxs[integral_type_size] : 0;
574             VOGL_ASSERT((!integral_type_size) || (val == -(s_signed_mins[integral_type_size] + 1)));
575             return val;
576         }
577
578         inline uint64_t get_unsigned_max_value(uint integral_type_size)
579         {
580             VOGL_ASSERT(integral_type_size <= 8);
581             uint64_t val = (integral_type_size <= 8) ? s_unsigned_maxes[integral_type_size] : 0;
582             VOGL_ASSERT((integral_type_size == 8) ? (val == cUINT64_MAX) : (val == ((1ULL << (integral_type_size * 8U)) - 1ULL)));
583             uint64_t k = (static_cast<uint64_t>(1ULL | (s_signed_maxs[integral_type_size]) << 1U));
584             VOGL_NOTE_UNUSED(k);
585             VOGL_ASSERT((!integral_type_size) || (val == k));
586             return val;
587         }
588
589         inline bool is_8bit(uint64_t val)
590         {
591             return val <= cUINT8_MAX;
592         }
593
594         inline bool is_8bit(int64_t val)
595         {
596             return (val >= cINT8_MIN) && (val <= cINT8_MAX);
597         }
598
599         inline bool is_16bit(uint64_t val)
600         {
601             return val <= cUINT16_MAX;
602         }
603
604         inline bool is_16bit(int64_t val)
605         {
606             return (val >= cINT16_MIN) && (val <= cINT16_MAX);
607         }
608
609         inline bool is_32bit(uint64_t val)
610         {
611             return val <= cUINT32_MAX;
612         }
613
614         inline bool is_32bit(int64_t val)
615         {
616             return (val >= cINT32_MIN) && (val <= cINT32_MAX);
617         }
618
619         // map_value: attempts to map the specified value from F to T, or returns def_value if the map isn't possible
620
621         template <typename V, typename F, typename T>
622         inline T map_value(V value, T def_value, F f0, T t0)
623         {
624             if (value == f0)
625                 return t0;
626             return def_value;
627         }
628
629         template <typename V, typename F, typename T>
630         inline T map_value(V value, T def_value, F f0, T t0, F f1, T t1)
631         {
632             if (value == f0)
633                 return t0;
634             else if (value == f1)
635                 return t1;
636             return def_value;
637         }
638
639         template <typename V, typename F, typename T>
640         inline T map_value(V value, T def_value, F f0, T t0, F f1, T t1, F f2, T t2)
641         {
642             if (value == f0)
643                 return t0;
644             else if (value == f1)
645                 return t1;
646             else if (value == f2)
647                 return t2;
648             return def_value;
649         }
650
651         template <typename V, typename F, typename T>
652         inline T map_value(V value, T def_value, F f0, T t0, F f1, T t1, F f2, T t2, F f3, T t3)
653         {
654             if (value == f0)
655                 return t0;
656             else if (value == f1)
657                 return t1;
658             else if (value == f2)
659                 return t2;
660             else if (value == f3)
661                 return t3;
662             return def_value;
663         }
664
665         template <typename V, typename F, typename T>
666         inline T map_value(V value, T def_value, F f0, T t0, F f1, T t1, F f2, T t2, F f3, T t3, F f4, T t4)
667         {
668             if (value == f0)
669                 return t0;
670             else if (value == f1)
671                 return t1;
672             else if (value == f2)
673                 return t2;
674             else if (value == f3)
675                 return t3;
676             else if (value == f4)
677                 return t4;
678             return def_value;
679         }
680
681         template <typename V, typename F, typename T>
682         inline T map_value(V value, T def_value, F f0, T t0, F f1, T t1, F f2, T t2, F f3, T t3, F f4, T t4, F f5, T t5)
683         {
684             if (value == f0)
685                 return t0;
686             else if (value == f1)
687                 return t1;
688             else if (value == f2)
689                 return t2;
690             else if (value == f3)
691                 return t3;
692             else if (value == f4)
693                 return t4;
694             else if (value == f5)
695                 return t5;
696             return def_value;
697         }
698
699         template <typename V, typename F, typename T>
700         inline T map_value(V value, T def_value, F f0, T t0, F f1, T t1, F f2, T t2, F f3, T t3, F f4, T t4, F f5, T t5, F f6, T t6)
701         {
702             if (value == f0)
703                 return t0;
704             else if (value == f1)
705                 return t1;
706             else if (value == f2)
707                 return t2;
708             else if (value == f3)
709                 return t3;
710             else if (value == f4)
711                 return t4;
712             else if (value == f5)
713                 return t5;
714             else if (value == f6)
715                 return t6;
716             return def_value;
717         }
718
719         template <typename V, typename F, typename T>
720         inline T map_value(V value, T def_value, F f0, T t0, F f1, T t1, F f2, T t2, F f3, T t3, F f4, T t4, F f5, T t5, F f6, T t6, F f7, T t7)
721         {
722             if (value == f0)
723                 return t0;
724             else if (value == f1)
725                 return t1;
726             else if (value == f2)
727                 return t2;
728             else if (value == f3)
729                 return t3;
730             else if (value == f4)
731                 return t4;
732             else if (value == f5)
733                 return t5;
734             else if (value == f6)
735                 return t6;
736             else if (value == f7)
737                 return t7;
738             return def_value;
739         }
740
741         template <typename V, typename F, typename T>
742         inline T map_value(V value, T def_value, F f0, T t0, F f1, T t1, F f2, T t2, F f3, T t3, F f4, T t4, F f5, T t5, F f6, T t6, F f7, T t7, F f8, T t8)
743         {
744             if (value == f0)
745                 return t0;
746             else if (value == f1)
747                 return t1;
748             else if (value == f2)
749                 return t2;
750             else if (value == f3)
751                 return t3;
752             else if (value == f4)
753                 return t4;
754             else if (value == f5)
755                 return t5;
756             else if (value == f6)
757                 return t6;
758             else if (value == f7)
759                 return t7;
760             else if (value == f8)
761                 return t8;
762             return def_value;
763         }
764
765         template <typename V, typename F, typename T>
766         inline T map_value(V value, T def_value, F f0, T t0, F f1, T t1, F f2, T t2, F f3, T t3, F f4, T t4, F f5, T t5, F f6, T t6, F f7, T t7, F f8, T t8, F f9, T t9)
767         {
768             if (value == f0)
769                 return t0;
770             else if (value == f1)
771                 return t1;
772             else if (value == f2)
773                 return t2;
774             else if (value == f3)
775                 return t3;
776             else if (value == f4)
777                 return t4;
778             else if (value == f5)
779                 return t5;
780             else if (value == f6)
781                 return t6;
782             else if (value == f7)
783                 return t7;
784             else if (value == f8)
785                 return t8;
786             else if (value == f9)
787                 return t9;
788             return def_value;
789         }
790
791         template <typename V, typename F, typename T>
792         inline T map_value(V value, T def_value, F f0, T t0, F f1, T t1, F f2, T t2, F f3, T t3, F f4, T t4, F f5, T t5, F f6, T t6, F f7, T t7, F f8, T t8, F f9, T t9, F f10, T t10)
793         {
794             if (value == f0)
795                 return t0;
796             else if (value == f1)
797                 return t1;
798             else if (value == f2)
799                 return t2;
800             else if (value == f3)
801                 return t3;
802             else if (value == f4)
803                 return t4;
804             else if (value == f5)
805                 return t5;
806             else if (value == f6)
807                 return t6;
808             else if (value == f7)
809                 return t7;
810             else if (value == f8)
811                 return t8;
812             else if (value == f9)
813                 return t9;
814             else if (value == f10)
815                 return t10;
816             return def_value;
817         }
818
819         // is_in_set: true if value is either v0, v1, etc.
820
821         template <typename V, typename T>
822         inline bool is_in_set(V value, T v0)
823         {
824             return value == v0;
825         }
826
827         template <typename V, typename T>
828         inline bool is_in_set(V value, T v0, T v1)
829         {
830             return (value == v0) || (value == v1);
831         }
832
833         template <typename V, typename T>
834         inline bool is_in_set(V value, T v0, T v1, T v2)
835         {
836             return (value == v0) || (value == v1) || (value == v2);
837         }
838
839         template <typename V, typename T>
840         inline bool is_in_set(V value, T v0, T v1, T v2, T v3)
841         {
842             return (value == v0) || (value == v1) || (value == v2) || (value == v3);
843         }
844
845         template <typename V, typename T>
846         inline bool is_in_set(V value, T v0, T v1, T v2, T v3, T v4)
847         {
848             return (value == v0) || (value == v1) || (value == v2) || (value == v3) || (value == v4);
849         }
850
851         template <typename V, typename T>
852         inline bool is_in_set(V value, T v0, T v1, T v2, T v3, T v4, T v5)
853         {
854             return (value == v0) || (value == v1) || (value == v2) || (value == v3) || (value == v4) || (value == v5);
855         }
856
857         template <typename V, typename T>
858         inline bool is_in_set(V value, T v0, T v1, T v2, T v3, T v4, T v5, T v6)
859         {
860             return (value == v0) || (value == v1) || (value == v2) || (value == v3) || (value == v4) || (value == v5) || (value == v6);
861         }
862
863         template <typename V, typename T>
864         inline bool is_in_set(V value, T v0, T v1, T v2, T v3, T v4, T v5, T v6, T v7)
865         {
866             return (value == v0) || (value == v1) || (value == v2) || (value == v3) || (value == v4) || (value == v5) || (value == v6) || (value == v7);
867         }
868
869         template <typename V, typename T>
870         inline bool is_in_set(V value, T v0, T v1, T v2, T v3, T v4, T v5, T v6, T v7, T v8)
871         {
872             return (value == v0) || (value == v1) || (value == v2) || (value == v3) || (value == v4) || (value == v5) || (value == v6) || (value == v7) || (value == v8);
873         }
874
875         template <typename V, typename T>
876         inline bool is_in_set(V value, T v0, T v1, T v2, T v3, T v4, T v5, T v6, T v7, T v8, T v9)
877         {
878             return (value == v0) || (value == v1) || (value == v2) || (value == v3) || (value == v4) || (value == v5) || (value == v6) || (value == v7) || (value == v8) || (value == v9);
879         }
880
881         template <typename V, typename T>
882         inline bool is_in_set(V value, T v0, T v1, T v2, T v3, T v4, T v5, T v6, T v7, T v8, T v9, T v10)
883         {
884             return (value == v0) || (value == v1) || (value == v2) || (value == v3) || (value == v4) || (value == v5) || (value == v6) || (value == v7) || (value == v8) || (value == v9) || (value == v10);
885         }
886
887         template <typename V, typename T>
888         inline bool is_in_set(V value, T v0, T v1, T v2, T v3, T v4, T v5, T v6, T v7, T v8, T v9, T v10, T v11)
889         {
890             return (value == v0) || (value == v1) || (value == v2) || (value == v3) || (value == v4) || (value == v5) || (value == v6) || (value == v7) || (value == v8) || (value == v9) || (value == v10) || (value == v11);
891         }
892
893         // is_not_in_set: true if value is != v0, and != v1, etc.
894
895         template <typename V, typename T>
896         inline bool is_not_in_set(V value, T v0)
897         {
898             return value != v0;
899         }
900
901         template <typename V, typename T>
902         inline bool is_not_in_set(V value, T v0, T v1)
903         {
904             return (value != v0) && (value != v1);
905         }
906
907         template <typename V, typename T>
908         inline bool is_not_in_set(V value, T v0, T v1, T v2)
909         {
910             return (value != v0) && (value != v1) && (value != v2);
911         }
912
913         template <typename V, typename T>
914         inline bool is_not_in_set(V value, T v0, T v1, T v2, T v3)
915         {
916             return (value != v0) && (value != v1) && (value != v2) && (value != v3);
917         }
918
919         template <typename V, typename T>
920         inline bool is_not_in_set(V value, T v0, T v1, T v2, T v3, T v4)
921         {
922             return (value != v0) && (value != v1) && (value != v2) && (value != v3) && (value != v4);
923         }
924
925         template <typename V, typename T>
926         inline bool is_not_in_set(V value, T v0, T v1, T v2, T v3, T v4, T v5)
927         {
928             return (value != v0) && (value != v1) && (value != v2) && (value != v3) && (value != v4) && (value != v5);
929         }
930
931         template <typename V, typename T>
932         inline bool is_not_in_set(V value, T v0, T v1, T v2, T v3, T v4, T v5, T v6)
933         {
934             return (value != v0) && (value != v1) && (value != v2) && (value != v3) && (value != v4) && (value != v5) && (value != v6);
935         }
936
937         template <typename V, typename T>
938         inline bool is_not_in_set(V value, T v0, T v1, T v2, T v3, T v4, T v5, T v6, T v7)
939         {
940             return (value != v0) && (value != v1) && (value != v2) && (value != v3) && (value != v4) && (value != v5) && (value != v6) && (value != v7);
941         }
942
943         template <typename V, typename T>
944         inline bool is_not_in_set(V value, T v0, T v1, T v2, T v3, T v4, T v5, T v6, T v7, T v8)
945         {
946             return (value != v0) && (value != v1) && (value != v2) && (value != v3) && (value != v4) && (value != v5) && (value != v6) && (value != v7) && (value != v8);
947         }
948
949         // map_to_index: tries to map value v0, v1, and returns its index, or returns def
950
951         template <typename V, typename T>
952         inline int map_to_index(V value, int def, T v0)
953         {
954             if (value == v0)
955                 return 0;
956             return def;
957         }
958
959         template <typename V, typename T>
960         inline int map_to_index(V value, int def, T v0, T v1)
961         {
962             if (value == v0)
963                 return 0;
964             else if (value == v1)
965                 return 1;
966             return def;
967         }
968
969         template <typename V, typename T>
970         inline int map_to_index(V value, int def, T v0, T v1, T v2)
971         {
972             if (value == v0)
973                 return 0;
974             else if (value == v1)
975                 return 1;
976             else if (value == v2)
977                 return 2;
978             return def;
979         }
980
981         template <typename V, typename T>
982         inline int map_to_index(V value, int def, T v0, T v1, T v2, T v3)
983         {
984             if (value == v0)
985                 return 0;
986             else if (value == v1)
987                 return 1;
988             else if (value == v2)
989                 return 2;
990             else if (value == v3)
991                 return 3;
992             return def;
993         }
994
995         template <typename V, typename T>
996         inline int map_to_index(V value, int def, T v0, T v1, T v2, T v3, T v4)
997         {
998             if (value == v0)
999                 return 0;
1000             else if (value == v1)
1001                 return 1;
1002             else if (value == v2)
1003                 return 2;
1004             else if (value == v3)
1005                 return 3;
1006             else if (value == v4)
1007                 return 4;
1008             return def;
1009         }
1010
1011         template <typename V, typename T>
1012         inline int map_to_index(V value, int def, T v0, T v1, T v2, T v3, T v4, T v5)
1013         {
1014             if (value == v0)
1015                 return 0;
1016             else if (value == v1)
1017                 return 1;
1018             else if (value == v2)
1019                 return 2;
1020             else if (value == v3)
1021                 return 3;
1022             else if (value == v4)
1023                 return 4;
1024             else if (value == v5)
1025                 return 5;
1026             return def;
1027         }
1028
1029         template <typename V, typename T>
1030         inline int map_to_index(V value, int def, T v0, T v1, T v2, T v3, T v4, T v5, T v6)
1031         {
1032             if (value == v0)
1033                 return 0;
1034             else if (value == v1)
1035                 return 1;
1036             else if (value == v2)
1037                 return 2;
1038             else if (value == v3)
1039                 return 3;
1040             else if (value == v4)
1041                 return 4;
1042             else if (value == v5)
1043                 return 5;
1044             else if (value == v6)
1045                 return 6;
1046             return def;
1047         }
1048
1049         template <typename V, typename T>
1050         inline int map_to_index(V value, int def, T v0, T v1, T v2, T v3, T v4, T v5, T v6, T v7)
1051         {
1052             if (value == v0)
1053                 return 0;
1054             else if (value == v1)
1055                 return 1;
1056             else if (value == v2)
1057                 return 2;
1058             else if (value == v3)
1059                 return 3;
1060             else if (value == v4)
1061                 return 4;
1062             else if (value == v5)
1063                 return 5;
1064             else if (value == v6)
1065                 return 6;
1066             else if (value == v7)
1067                 return 7;
1068             return def;
1069         }
1070
1071         template <typename V, typename T>
1072         inline int map_to_index(V value, int def, T v0, T v1, T v2, T v3, T v4, T v5, T v6, T v7, T v8)
1073         {
1074             if (value == v0)
1075                 return 0;
1076             else if (value == v1)
1077                 return 1;
1078             else if (value == v2)
1079                 return 2;
1080             else if (value == v3)
1081                 return 3;
1082             else if (value == v4)
1083                 return 4;
1084             else if (value == v5)
1085                 return 5;
1086             else if (value == v6)
1087                 return 6;
1088             else if (value == v7)
1089                 return 7;
1090             else if (value == v8)
1091                 return 8;
1092             return def;
1093         }
1094
1095         // Finds value in the specified static array, or -1 if it can't be found
1096         template <typename V, typename T, size_t size>
1097         inline int64_t find_value_in_array(V value, T (&p)[size])
1098         {
1099             for (size_t i = 0; i < size; i++)
1100                 if (value == p[i])
1101                     return i;
1102             return -1;
1103         }
1104
1105         // Finds value in the specified array, or -1 if it can't be found
1106         template <typename V, typename T>
1107         inline int64_t find_value_in_array(V value, T *p, size_t size)
1108         {
1109             for (size_t i = 0; i < size; i++)
1110                 if (value == p[i])
1111                     return i;
1112             return -1;
1113         }
1114
1115         // Should be called before using RDTSC().
1116         bool init_rdtsc();
1117
1118         inline uint64_t get_rdtsc()
1119         {
1120 #if defined(__GNUC__)
1121             unsigned int hi, lo;
1122             __asm__ volatile("rdtsc" : "=a"(lo), "=d"(hi));
1123             return ((uint64_t)hi << 32) | lo;
1124 #else
1125             return __rdtsc();
1126 #endif
1127         }
1128
1129         inline uint64_t RDTSC()
1130         {
1131 #if defined(VOGL_USE_LINUX_API)
1132             extern int g_reliable_rdtsc;
1133             if (g_reliable_rdtsc == -1)
1134                 init_rdtsc();
1135             if (g_reliable_rdtsc == 0)
1136             {
1137                 //$ TODO: Should just use SDL_GetPerformanceCounter?
1138                 struct timespec time;
1139                 clock_gettime(CLOCK_MONOTONIC, &time);
1140                 return ((uint64_t)time.tv_sec * 1000000000) + time.tv_nsec;
1141             }
1142 #endif
1143             return get_rdtsc();
1144         }
1145
1146     } // namespace utils
1147
1148 } // namespace vogl