Przeglądaj źródła

Merge branch 'master' of https://github.com/MikePopoloski/bx

Mike Popoloski 11 lat temu
rodzic
commit
8ca8788c27

+ 19 - 12
3rdparty/UnitTest++/src/Config.h

@@ -4,23 +4,30 @@
 // Standard defines documented here: http://predef.sourceforge.net
 
 #if defined(_MSC_VER)
-    #pragma warning(disable:4127) // conditional expression is constant
-	#pragma warning(disable:4702) // unreachable code
-	#pragma warning(disable:4722) // destructor never returns, potential memory leak
-
-	#if (_MSC_VER == 1200)  // VC6
-		#pragma warning(disable:4786)
-		#pragma warning(disable:4290)
-	#endif
+#	pragma warning(disable:4127) // conditional expression is constant
+#	pragma warning(disable:4702) // unreachable code
+#	pragma warning(disable:4722) // destructor never returns, potential memory leak
+
+#	if (_MSC_VER == 1200)  // VC6
+#		pragma warning(disable:4786)
+#		pragma warning(disable:4290)
+#	endif
 #endif
 
-#if defined(unix) || defined(__unix__) || defined(__unix) || defined(linux) || \
-    defined(__APPLE__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__)        
-    #define UNITTEST_POSIX
+#if defined(unix) \
+	|| defined(__unix__) \
+	|| defined(__unix) \
+	|| defined(linux) \
+	|| defined(__APPLE__) \
+	|| defined(__NetBSD__) \
+	|| defined(__OpenBSD__) \
+	|| defined(__FreeBSD__) \
+	|| defined(__native_client__)
+#	define UNITTEST_POSIX
 #endif
 
 #if defined(__MINGW32__)
-    #define UNITTEST_MINGW
+#	define UNITTEST_MINGW
 #endif
 
 // by default, MemoryOutStream is implemented in terms of std::ostringstream, which can be expensive.

+ 11 - 0
3rdparty/UnitTest++/src/Posix/SignalTranslator.cpp

@@ -2,6 +2,16 @@
 
 namespace UnitTest {
 
+#if defined(__native_client__)
+SignalTranslator::SignalTranslator()
+{
+}
+
+SignalTranslator::~SignalTranslator()
+{
+}
+#else
+
 sigjmp_buf* SignalTranslator::s_jumpTarget = 0;
 
 namespace {
@@ -42,5 +52,6 @@ SignalTranslator::~SignalTranslator()
     s_jumpTarget = m_oldJumpTarget;
 }
 
+#endif // defined(__native_client__)
 
 }

+ 14 - 7
3rdparty/UnitTest++/src/Posix/SignalTranslator.h

@@ -12,6 +12,8 @@ public:
     SignalTranslator();
     ~SignalTranslator();
 
+#if defined(__native_client__)
+#else
     static sigjmp_buf* s_jumpTarget;
 
 private:
@@ -24,18 +26,23 @@ private:
     struct sigaction m_old_SIGBUS_action;
 //    struct sigaction m_old_SIGABRT_action;
 //    struct sigaction m_old_SIGALRM_action;
+#endif // defined(__native_client__)
 };
 
-#if !defined (__GNUC__)
-    #define UNITTEST_EXTENSION
+#if !defined(__GNUC__) && !defined(__clang__)
+#	define UNITTEST_EXTENSION
 #else
-    #define UNITTEST_EXTENSION __extension__
+#	define UNITTEST_EXTENSION __extension__
 #endif
 
-#define UNITTEST_THROW_SIGNALS \
-	UnitTest::SignalTranslator sig; \
-	if (UNITTEST_EXTENSION sigsetjmp(*UnitTest::SignalTranslator::s_jumpTarget, 1) != 0) \
-        throw ("Unhandled system exception"); 
+#if defined(__native_client__)
+#	define UNITTEST_THROW_SIGNALS
+#else
+#	define UNITTEST_THROW_SIGNALS \
+		UnitTest::SignalTranslator sig; \
+		if (UNITTEST_EXTENSION sigsetjmp(*UnitTest::SignalTranslator::s_jumpTarget, 1) != 0) \
+			throw ("Unhandled system exception"); 
+#endif // defined(__native_client__)
 
 }
 

+ 1 - 0
include/bx/cl.h

@@ -888,6 +888,7 @@ namespace bx
 			if (0 == ref)
 			{
 				dlclose(m_handle);
+				m_handle = NULL;
 			}
 
 			return ref;

+ 482 - 0
include/bx/float4_langext.h

@@ -0,0 +1,482 @@
+/*
+ * Copyright 2010-2014 Branimir Karadzic. All rights reserved.
+ * License: http://www.opensource.org/licenses/BSD-2-Clause
+ */
+
+#ifndef BX_FLOAT4_LANGEXT_H_HEADER_GUARD
+#define BX_FLOAT4_LANGEXT_H_HEADER_GUARD
+
+#include <math.h>
+
+namespace bx
+{
+	typedef union float4_t
+	{
+		float    __attribute__((vector_size(16))) vf;
+		int32_t  __attribute__((vector_size(16))) vi;
+		uint32_t __attribute__((vector_size(16))) vu;
+		float    fxyzw[4];
+		int32_t  ixyzw[4];
+		uint32_t uxyzw[4];
+
+	} float4_t;
+
+#define ELEMx 0
+#define ELEMy 1
+#define ELEMz 2
+#define ELEMw 3
+#define IMPLEMENT_SWIZZLE(_x, _y, _z, _w) \
+			BX_FLOAT4_FORCE_INLINE float4_t float4_swiz_##_x##_y##_z##_w(float4_t _a) \
+			{ \
+				float4_t result; \
+				result.vf = __builtin_shufflevector(_a.vf, _a.vf, ELEM##_x, ELEM##_y, ELEM##_z, ELEM##_w); \
+				return result; \
+			}
+
+#include "float4_swizzle.inl"
+
+#undef IMPLEMENT_SWIZZLE
+#undef ELEMw
+#undef ELEMz
+#undef ELEMy
+#undef ELEMx
+
+#define IMPLEMENT_TEST(_xyzw, _mask) \
+			BX_FLOAT4_FORCE_INLINE bool float4_test_any_##_xyzw(float4_t _test) \
+			{ \
+				uint32_t tmp = ( (_test.uxyzw[3]>>31)<<3) \
+				             | ( (_test.uxyzw[2]>>31)<<2) \
+				             | ( (_test.uxyzw[1]>>31)<<1) \
+				             | (  _test.uxyzw[0]>>31)     \
+				             ; \
+				return 0 != (tmp&(_mask) ); \
+			} \
+			\
+			BX_FLOAT4_FORCE_INLINE bool float4_test_all_##_xyzw(float4_t _test) \
+			{ \
+				uint32_t tmp = ( (_test.uxyzw[3]>>31)<<3) \
+				             | ( (_test.uxyzw[2]>>31)<<2) \
+				             | ( (_test.uxyzw[1]>>31)<<1) \
+				             | (  _test.uxyzw[0]>>31)     \
+				             ; \
+				return (_mask) == (tmp&(_mask) ); \
+			}
+
+IMPLEMENT_TEST(x    , 0x1);
+IMPLEMENT_TEST(y    , 0x2);
+IMPLEMENT_TEST(xy   , 0x3);
+IMPLEMENT_TEST(z    , 0x4);
+IMPLEMENT_TEST(xz   , 0x5);
+IMPLEMENT_TEST(yz   , 0x6);
+IMPLEMENT_TEST(xyz  , 0x7);
+IMPLEMENT_TEST(w    , 0x8);
+IMPLEMENT_TEST(xw   , 0x9);
+IMPLEMENT_TEST(yw   , 0xa);
+IMPLEMENT_TEST(xyw  , 0xb);
+IMPLEMENT_TEST(zw   , 0xc);
+IMPLEMENT_TEST(xzw  , 0xd);
+IMPLEMENT_TEST(yzw  , 0xe);
+IMPLEMENT_TEST(xyzw , 0xf);
+
+#undef IMPLEMENT_TEST
+
+	BX_FLOAT4_FORCE_INLINE float4_t float4_shuf_xyAB(float4_t _a, float4_t _b)
+	{
+		float4_t result;
+		result.vf = __builtin_shufflevector(_a.vf, _b.vf, 0, 1, 4, 5);
+		return result;
+	}
+
+	BX_FLOAT4_FORCE_INLINE float4_t float4_shuf_ABxy(float4_t _a, float4_t _b)
+	{
+		float4_t result;
+		result.vf = __builtin_shufflevector(_a.vf, _b.vf, 4, 5, 0, 1);
+		return result;
+	}
+
+	BX_FLOAT4_FORCE_INLINE float4_t float4_shuf_CDzw(float4_t _a, float4_t _b)
+	{
+		float4_t result;
+		result.vf = __builtin_shufflevector(_a.vf, _b.vf, 5, 7, 2, 3);
+		return result;
+	}
+
+	BX_FLOAT4_FORCE_INLINE float4_t float4_shuf_zwCD(float4_t _a, float4_t _b)
+	{
+		float4_t result;
+		result.vf = __builtin_shufflevector(_a.vf, _b.vf, 2, 3, 5, 7);
+		return result;
+	}
+
+	BX_FLOAT4_FORCE_INLINE float4_t float4_shuf_xAyB(float4_t _a, float4_t _b)
+	{
+		float4_t result;
+		result.vf = __builtin_shufflevector(_a.vf, _b.vf, 0, 4, 1, 5);
+		return result;
+	}
+
+	BX_FLOAT4_FORCE_INLINE float4_t float4_shuf_yBxA(float4_t _a, float4_t _b)
+	{
+		float4_t result;
+		result.vf = __builtin_shufflevector(_a.vf, _b.vf, 1, 5, 0, 4);
+		return result;
+	}
+
+	BX_FLOAT4_FORCE_INLINE float4_t float4_shuf_zCwD(float4_t _a, float4_t _b)
+	{
+		float4_t result;
+		result.vf = __builtin_shufflevector(_a.vf, _b.vf, 2, 6, 3, 7);
+		return result;
+	}
+
+	BX_FLOAT4_FORCE_INLINE float4_t float4_shuf_CzDw(float4_t _a, float4_t _b)
+	{
+		float4_t result;
+		result.vf = __builtin_shufflevector(_a.vf, _b.vf, 6, 2, 7, 3);
+		return result;
+	}
+
+	BX_FLOAT4_FORCE_INLINE float4_t float4_shuf_xAzC(float4_t _a, float4_t _b)
+	{
+		float4_t result;
+		result.vf = __builtin_shufflevector(_a.vf, _b.vf, 0, 4, 2, 6);
+		return result;
+	}
+
+	BX_FLOAT4_FORCE_INLINE float4_t float4_shuf_yBwD(float4_t _a, float4_t _b)
+	{
+		float4_t result;
+		result.vf = __builtin_shufflevector(_a.vf, _b.vf, 1, 5, 3, 7);
+		return result;
+	}
+
+	BX_FLOAT4_FORCE_INLINE float float4_x(float4_t _a)
+	{
+		return _a.fxyzw[0];
+	}
+
+	BX_FLOAT4_FORCE_INLINE float float4_y(float4_t _a)
+	{
+		return _a.fxyzw[1];
+	}
+
+	BX_FLOAT4_FORCE_INLINE float float4_z(float4_t _a)
+	{
+		return _a.fxyzw[2];
+	}
+
+	BX_FLOAT4_FORCE_INLINE float float4_w(float4_t _a)
+	{
+		return _a.fxyzw[3];
+	}
+
+	BX_FLOAT4_FORCE_INLINE float4_t float4_ld(const void* _ptr)
+	{
+		const uint32_t* input = reinterpret_cast<const uint32_t*>(_ptr);
+		float4_t result;
+		result.uxyzw[0] = input[0];
+		result.uxyzw[1] = input[1];
+		result.uxyzw[2] = input[2];
+		result.uxyzw[3] = input[3];
+		return result;
+	}
+
+	BX_FLOAT4_FORCE_INLINE void float4_st(void* _ptr, float4_t _a)
+	{
+		uint32_t* result = reinterpret_cast<uint32_t*>(_ptr);
+		result[0] = _a.uxyzw[0];
+		result[1] = _a.uxyzw[1];
+		result[2] = _a.uxyzw[2];
+		result[3] = _a.uxyzw[3];
+	}
+
+	BX_FLOAT4_FORCE_INLINE void float4_stx(void* _ptr, float4_t _a)
+	{
+		uint32_t* result = reinterpret_cast<uint32_t*>(_ptr);
+		result[0] = _a.uxyzw[0];
+	}
+
+	BX_FLOAT4_FORCE_INLINE void float4_stream(void* _ptr, float4_t _a)
+	{
+		uint32_t* result = reinterpret_cast<uint32_t*>(_ptr);
+		result[0] = _a.uxyzw[0];
+		result[1] = _a.uxyzw[1];
+		result[2] = _a.uxyzw[2];
+		result[3] = _a.uxyzw[3];
+	}
+
+	BX_FLOAT4_FORCE_INLINE float4_t float4_ld(float _x, float _y, float _z, float _w)
+	{
+		float4_t result;
+		result.vf = { _x, _y, _z, _w };
+		return result;
+	}
+
+	BX_FLOAT4_FORCE_INLINE float4_t float4_ild(uint32_t _x, uint32_t _y, uint32_t _z, uint32_t _w)
+	{
+		float4_t result;
+		result.vu = { _x, _y, _z, _w };
+		return result;
+	}
+
+	BX_FLOAT4_FORCE_INLINE float4_t float4_splat(const void* _ptr)
+	{
+		const uint32_t val = *reinterpret_cast<const uint32_t*>(_ptr);
+		float4_t result;
+		result.vu = { val, val, val, val };
+		return result;
+	}
+
+	BX_FLOAT4_FORCE_INLINE float4_t float4_splat(float _a)
+	{
+		return float4_ld(_a, _a, _a, _a);
+	}
+
+	BX_FLOAT4_FORCE_INLINE float4_t float4_isplat(uint32_t _a)
+	{
+		return float4_ild(_a, _a, _a, _a);
+	}
+
+	BX_FLOAT4_FORCE_INLINE float4_t float4_zero()
+	{
+		return float4_ild(0, 0, 0, 0);
+	}
+
+	BX_FLOAT4_FORCE_INLINE float4_t float4_itof(float4_t _a)
+	{
+		float4_t result;
+		result.vf = __builtin_convertvector(_a.vi, float __attribute__((vector_size(16))) );
+		return result;
+	}
+
+	BX_FLOAT4_FORCE_INLINE float4_t float4_ftoi(float4_t _a)
+	{
+		float4_t result;
+		result.vi = __builtin_convertvector(_a.vf, int32_t __attribute__((vector_size(16))) );
+		return result;
+	}
+
+	BX_FLOAT4_FORCE_INLINE float4_t float4_round(float4_t _a)
+	{
+		const float4_t tmp    = float4_ftoi(_a);
+		const float4_t result = float4_itof(tmp);
+
+		return result;
+	}
+
+	BX_FLOAT4_FORCE_INLINE float4_t float4_add(float4_t _a, float4_t _b)
+	{
+		float4_t result;
+		result.vf = _a.vf + _b.vf;
+		return result;
+	}
+
+	BX_FLOAT4_FORCE_INLINE float4_t float4_sub(float4_t _a, float4_t _b)
+	{
+		float4_t result;
+		result.vf = _a.vf - _b.vf;
+		return result;
+	}
+
+	BX_FLOAT4_FORCE_INLINE float4_t float4_mul(float4_t _a, float4_t _b)
+	{
+		float4_t result;
+		result.vf = _a.vf * _b.vf;
+		return result;
+	}
+
+	BX_FLOAT4_FORCE_INLINE float4_t float4_div(float4_t _a, float4_t _b)
+	{
+		float4_t result;
+		result.vf = _a.vf / _b.vf;
+		return result;
+	}
+
+#if 0
+	BX_FLOAT4_FORCE_INLINE float4_t float4_rcp_est(float4_t _a)
+	{
+		float4_t result;
+		const float4_t one = float4_splat(1.0f);
+		result.vf = one / _a.vf;
+		return result;
+	}
+#endif // 0
+
+	BX_FLOAT4_FORCE_INLINE float4_t float4_sqrt(float4_t _a)
+	{
+		float4_t result;
+		result.vf[0] = sqrtf(_a.vf[0]);
+		result.vf[1] = sqrtf(_a.vf[1]);
+		result.vf[2] = sqrtf(_a.vf[2]);
+		result.vf[3] = sqrtf(_a.vf[3]);
+		return result;
+	}
+
+	BX_FLOAT4_FORCE_INLINE float4_t float4_rsqrt_est(float4_t _a)
+	{
+		float4_t result;
+		result.vf[0] = 1.0f / sqrtf(_a.vf[0]);
+		result.vf[1] = 1.0f / sqrtf(_a.vf[1]);
+		result.vf[2] = 1.0f / sqrtf(_a.vf[2]);
+		result.vf[3] = 1.0f / sqrtf(_a.vf[3]);
+		return result;
+	}
+
+	BX_FLOAT4_FORCE_INLINE float4_t float4_cmpeq(float4_t _a, float4_t _b)
+	{
+		float4_t result;
+		result.vi = _a.vf == _b.vf;
+		return result;
+	}
+
+	BX_FLOAT4_FORCE_INLINE float4_t float4_cmplt(float4_t _a, float4_t _b)
+	{
+		float4_t result;
+		result.vi = _a.vf < _b.vf;
+		return result;
+	}
+
+	BX_FLOAT4_FORCE_INLINE float4_t float4_cmple(float4_t _a, float4_t _b)
+	{
+		float4_t result;
+		result.vi = _a.vf <= _b.vf;
+		return result;
+	}
+
+	BX_FLOAT4_FORCE_INLINE float4_t float4_cmpgt(float4_t _a, float4_t _b)
+	{
+		float4_t result;
+		result.vi = _a.vf > _b.vf;
+		return result;
+	}
+
+	BX_FLOAT4_FORCE_INLINE float4_t float4_cmpge(float4_t _a, float4_t _b)
+	{
+		float4_t result;
+		result.vi = _a.vf >= _b.vf;
+		return result;
+	}
+
+	BX_FLOAT4_FORCE_INLINE float4_t float4_and(float4_t _a, float4_t _b)
+	{
+		float4_t result;
+		result.vu = _a.vu & _b.vu;
+		return result;
+	}
+
+	BX_FLOAT4_FORCE_INLINE float4_t float4_andc(float4_t _a, float4_t _b)
+	{
+		float4_t result;
+		result.vu = _a.vu & ~_b.vu;
+		return result;
+	}
+
+	BX_FLOAT4_FORCE_INLINE float4_t float4_or(float4_t _a, float4_t _b)
+	{
+		float4_t result;
+		result.vu = _a.vu | _b.vu;
+		return result;
+	}
+
+	BX_FLOAT4_FORCE_INLINE float4_t float4_xor(float4_t _a, float4_t _b)
+	{
+		float4_t result;
+		result.vu = _a.vu ^ _b.vu;
+		return result;
+	}
+
+	BX_FLOAT4_FORCE_INLINE float4_t float4_sll(float4_t _a, int _count)
+	{
+		float4_t result;
+		const float4_t count = float4_isplat(_count);
+		result.vu = _a.vu << count.vi;
+		return result;
+	}
+
+	BX_FLOAT4_FORCE_INLINE float4_t float4_srl(float4_t _a, int _count)
+	{
+		float4_t result;
+		const float4_t count = float4_isplat(_count);
+		result.vu = _a.vu >> count.vi;
+		return result;
+	}
+
+	BX_FLOAT4_FORCE_INLINE float4_t float4_sra(float4_t _a, int _count)
+	{
+		float4_t result;
+		const float4_t count = float4_isplat(_count);
+		result.vi = _a.vi >> count.vi;
+		return result;
+	}
+
+	BX_FLOAT4_FORCE_INLINE float4_t float4_icmpeq(float4_t _a, float4_t _b)
+	{
+		float4_t result;
+		result.vi = _a.vi == _b.vi;
+		return result;
+	}
+
+	BX_FLOAT4_FORCE_INLINE float4_t float4_icmplt(float4_t _a, float4_t _b)
+	{
+		float4_t result;
+		result.vi = _a.vi < _b.vi;
+		return result;
+	}
+
+	BX_FLOAT4_FORCE_INLINE float4_t float4_icmpgt(float4_t _a, float4_t _b)
+	{
+		float4_t result;
+		result.vi = _a.vi > _b.vi;
+		return result;
+	}
+
+	BX_FLOAT4_FORCE_INLINE float4_t float4_iadd(float4_t _a, float4_t _b)
+	{
+		float4_t result;
+		result.vi = _a.vi + _b.vi;
+		return result;
+	}
+
+	BX_FLOAT4_FORCE_INLINE float4_t float4_isub(float4_t _a, float4_t _b)
+	{
+		float4_t result;
+		result.vi = _a.vi - _b.vi;
+		return result;
+	}
+
+} // namespace bx
+
+#define float4_rcp           float4_rcp_ni
+#define float4_orx           float4_orx_ni
+#define float4_orc           float4_orc_ni
+#define float4_neg           float4_neg_ni
+#define float4_madd          float4_madd_ni
+#define float4_nmsub         float4_nmsub_ni
+#define float4_div_nr        float4_div_nr_ni
+#define float4_selb          float4_selb_ni
+#define float4_sels          float4_sels_ni
+#define float4_not           float4_not_ni
+#define float4_abs           float4_abs_ni
+#define float4_clamp         float4_clamp_ni
+#define float4_lerp          float4_lerp_ni
+#define float4_rcp_est       float4_rcp_ni
+#define float4_rsqrt         float4_rsqrt_ni
+#define float4_rsqrt_nr      float4_rsqrt_nr_ni
+#define float4_rsqrt_carmack float4_rsqrt_carmack_ni
+#define float4_sqrt_nr       float4_sqrt_nr_ni
+#define float4_log2          float4_log2_ni
+#define float4_exp2          float4_exp2_ni
+#define float4_pow           float4_pow_ni
+#define float4_cross3        float4_cross3_ni
+#define float4_normalize3    float4_normalize3_ni
+#define float4_dot3          float4_dot3_ni
+#define float4_dot           float4_dot_ni
+#define float4_ceil          float4_ceil_ni
+#define float4_floor         float4_floor_ni
+#define float4_min           float4_min_ni
+#define float4_max           float4_max_ni
+#define float4_imin          float4_imin_ni
+#define float4_imax          float4_imax_ni
+#include "float4_ni.h"
+
+#endif // BX_FLOAT4_LANGEXT_H_HEADER_GUARD

+ 1 - 1
include/bx/float4_neon.h

@@ -1,5 +1,5 @@
 /*
- * Copyright 2010-2013 Branimir Karadzic. All rights reserved.
+ * Copyright 2010-2014 Branimir Karadzic. All rights reserved.
  * License: http://www.opensource.org/licenses/BSD-2-Clause
  */
 

+ 18 - 2
include/bx/float4_ni.h

@@ -1,5 +1,5 @@
 /*
- * Copyright 2010-2013 Branimir Karadzic. All rights reserved.
+ * Copyright 2010-2014 Branimir Karadzic. All rights reserved.
  * License: http://www.opensource.org/licenses/BSD-2-Clause
  */
 
@@ -57,7 +57,7 @@ namespace bx
 	{
 		const float4_t one    = float4_splat(1.0f);
 		const float4_t result = float4_div(one, _a);
-		
+
 		return result;
 	}
 
@@ -115,6 +115,22 @@ namespace bx
 		return result;
 	}
 
+	BX_FLOAT4_INLINE float4_t float4_min_ni(float4_t _a, float4_t _b)
+	{
+		const float4_t mask   = float4_cmplt(_a, _b);
+		const float4_t result = float4_selb(mask, _a, _b);
+
+		return result;
+	}
+
+	BX_FLOAT4_INLINE float4_t float4_max_ni(float4_t _a, float4_t _b)
+	{
+		const float4_t mask   = float4_cmpgt(_a, _b);
+		const float4_t result = float4_selb(mask, _a, _b);
+
+		return result;
+	}
+
 	BX_FLOAT4_INLINE float4_t float4_abs_ni(float4_t _a)
 	{
 		const float4_t a_neg  = float4_neg(_a);

+ 3 - 3
include/bx/float4_ref.h

@@ -1,5 +1,5 @@
 /*
- * Copyright 2010-2013 Branimir Karadzic. All rights reserved.
+ * Copyright 2010-2014 Branimir Karadzic. All rights reserved.
  * License: http://www.opensource.org/licenses/BSD-2-Clause
  */
 
@@ -47,7 +47,7 @@ namespace bx
 				uint32_t tmp = ( (_test.uxyzw[3]>>31)<<3) \
 				             | ( (_test.uxyzw[2]>>31)<<2) \
 				             | ( (_test.uxyzw[1]>>31)<<1) \
-				             | (_test.uxyzw[0]>>31) \
+				             | (  _test.uxyzw[0]>>31)     \
 				             ; \
 				return 0 != (tmp&(_mask) ); \
 			} \
@@ -57,7 +57,7 @@ namespace bx
 				uint32_t tmp = ( (_test.uxyzw[3]>>31)<<3) \
 				             | ( (_test.uxyzw[2]>>31)<<2) \
 				             | ( (_test.uxyzw[1]>>31)<<1) \
-				             | (_test.uxyzw[0]>>31) \
+				             | (  _test.uxyzw[0]>>31)     \
 				             ; \
 				return (_mask) == (tmp&(_mask) ); \
 			}

+ 1 - 1
include/bx/float4_sse.h

@@ -1,5 +1,5 @@
 /*
- * Copyright 2010-2013 Branimir Karadzic. All rights reserved.
+ * Copyright 2010-2014 Branimir Karadzic. All rights reserved.
  * License: http://www.opensource.org/licenses/BSD-2-Clause
  */
 

+ 1 - 1
include/bx/float4_swizzle.inl

@@ -1,5 +1,5 @@
 /*
- * Copyright 2010-2013 Branimir Karadzic. All rights reserved.
+ * Copyright 2010-2014 Branimir Karadzic. All rights reserved.
  * License: http://www.opensource.org/licenses/BSD-2-Clause
  */
 

+ 3 - 1
include/bx/float4_t.h

@@ -1,5 +1,5 @@
 /*
- * Copyright 2010-2013 Branimir Karadzic. All rights reserved.
+ * Copyright 2010-2014 Branimir Karadzic. All rights reserved.
  * License: http://www.opensource.org/licenses/BSD-2-Clause
  */
 
@@ -15,6 +15,8 @@
 #	include "float4_sse.h"
 #elif __ARM_NEON__ && !BX_COMPILER_CLANG
 #	include "float4_neon.h"
+#elif 0 // BX_COMPILER_CLANG
+#	include "float4_langext.h"
 #else
 #	pragma message("************************************\nUsing SIMD reference implementation!\n************************************")
 #	include "float4_ref.h"

+ 1 - 1
include/bx/float4x4_t.h

@@ -1,5 +1,5 @@
 /*
- * Copyright 2010-2013 Branimir Karadzic. All rights reserved.
+ * Copyright 2010-2014 Branimir Karadzic. All rights reserved.
  * License: http://www.opensource.org/licenses/BSD-2-Clause
  */
 

+ 78 - 4
include/bx/fpumath.h

@@ -34,6 +34,16 @@ namespace bx
 		return _a > _b ? _a : _b;
 	}
 
+	inline float fmin3(float _a, float _b, float _c)
+	{
+		return fmin(_a, fmin(_b, _c) );
+	}
+
+	inline float fmax3(float _a, float _b, float _c)
+	{
+		return fmax(_a, fmax(_b, _c) );
+	}
+
 	inline float fclamp(float _a, float _min, float _max)
 	{
 		return fmin(fmax(_a, _min), _max);
@@ -54,6 +64,26 @@ namespace bx
 		return _a < 0.0f ? -1.0f : 1.0f;
 	}
 
+	inline float fstep(float _edge, float _a)
+	{
+		return _a < _edge ? 0.0f : 1.0f;
+	}
+
+	inline float fabsolute(float _a)
+	{
+		return fabsf(_a);
+	}
+
+	inline float fsqrt(float _a)
+	{
+		return sqrtf(_a);
+	}
+
+	inline float ffract(float _a)
+	{
+		return _a - floorf(_a);
+	}
+
 	inline void vec3Move(float* __restrict _result, const float* __restrict _a)
 	{
 		_result[0] = _a[0];
@@ -63,9 +93,9 @@ namespace bx
 
 	inline void vec3Abs(float* __restrict _result, const float* __restrict _a)
 	{
-		_result[0] = fabsf(_a[0]);
-		_result[1] = fabsf(_a[1]);
-		_result[2] = fabsf(_a[2]);
+		_result[0] = fabsolute(_a[0]);
+		_result[1] = fabsolute(_a[1]);
+		_result[2] = fabsolute(_a[2]);
 	}
 
 	inline void vec3Neg(float* __restrict _result, const float* __restrict _a)
@@ -117,7 +147,7 @@ namespace bx
 
 	inline float vec3Length(const float* _a)
 	{
-		return sqrtf(vec3Dot(_a, _a) );
+		return fsqrt(vec3Dot(_a, _a) );
 	}
 
 	inline float vec3Norm(float* __restrict _result, const float* __restrict _a)
@@ -567,6 +597,50 @@ namespace bx
 		_result[2] = normal[2];
 		_result[3] = -vec3Dot(normal, _va);
 	}
+
+	inline void rgbToHsv(float _hsv[3], const float _rgb[3])
+	{
+		const float rr = _rgb[0];
+		const float gg = _rgb[1];
+		const float bb = _rgb[2];
+
+		const float s0 = fstep(bb, gg);
+
+		const float px = flerp(bb,        gg,         s0);
+		const float py = flerp(gg,        bb,         s0);
+		const float pz = flerp(-1.0f,     0.0f,       s0);
+		const float pw = flerp(2.0f/3.0f, -1.0f/3.0f, s0);
+
+		const float s1 = fstep(px, rr);
+
+		const float qx = flerp(px, rr, s1);
+		const float qy = py;
+		const float qz = flerp(pw, pz, s1);
+		const float qw = flerp(rr, px, s1);
+
+		const float dd = qx - fmin(qw, qy);
+		const float ee = 1.0e-10f;
+
+		_hsv[0] = fabsolute(qz + (qw - qy) / (6.0f * dd + ee) );
+		_hsv[1] = dd / (qx + ee);
+		_hsv[2] = qx;
+	}
+
+	inline void hsvToRgb(float _rgb[3], const float _hsv[3])
+	{
+		const float hh = _hsv[0];
+		const float ss = _hsv[1];
+		const float vv = _hsv[2];
+
+		const float px = fabsolute(ffract(hh + 1.0f     ) * 6.0f - 3.0f);
+		const float py = fabsolute(ffract(hh + 2.0f/3.0f) * 6.0f - 3.0f);
+		const float pz = fabsolute(ffract(hh + 1.0f/3.0f) * 6.0f - 3.0f);
+
+		_rgb[0] = vv * flerp(1.0f, fsaturate(px - 1.0f), ss);
+		_rgb[1] = vv * flerp(1.0f, fsaturate(py - 1.0f), ss);
+		_rgb[2] = vv * flerp(1.0f, fsaturate(pz - 1.0f), ss);
+	}
+
 } // namespace bx
 
 #endif // BX_FPU_MATH_H_HEADER_GUARD

+ 1 - 0
include/bx/macros.h

@@ -157,6 +157,7 @@
 #ifndef BX_CONFIG_CRT_FILE_READER_WRITER
 #	define BX_CONFIG_CRT_FILE_READER_WRITER (0 \
 				|BX_PLATFORM_ANDROID \
+				|BX_PLATFORM_FREEBSD \
 				|BX_PLATFORM_IOS \
 				|BX_PLATFORM_LINUX \
 				|BX_PLATFORM_OSX \

+ 32 - 7
include/bx/os.h

@@ -10,15 +10,16 @@
 
 #if BX_PLATFORM_WINDOWS || BX_PLATFORM_WINRT
 #	include <windows.h>
-#elif BX_PLATFORM_NACL \
-	|| BX_PLATFORM_ANDROID \
-	|| BX_PLATFORM_LINUX \
-	|| BX_PLATFORM_OSX \
+#elif BX_PLATFORM_ANDROID \
+	|| BX_PLATFORM_EMSCRIPTEN \
+	|| BX_PLATFORM_FREEBSD \
 	|| BX_PLATFORM_IOS \
-	|| BX_PLATFORM_EMSCRIPTEN
+	|| BX_PLATFORM_LINUX \
+	|| BX_PLATFORM_NACL \
+	|| BX_PLATFORM_OSX
 
 #	include <sched.h> // sched_yield
-#	if BX_PLATFORM_IOS || BX_PLATFORM_OSX || BX_PLATFORM_NACL
+#	if BX_PLATFORM_FREEBSD || BX_PLATFORM_IOS || BX_PLATFORM_NACL || BX_PLATFORM_OSX
 #		include <pthread.h> // mach_port_t
 #	endif // BX_PLATFORM_IOS || BX_PLATFORM_OSX || BX_PLATFORM_NACL
 
@@ -39,6 +40,12 @@
 #	endif // BX_PLATFORM_ANDROID
 #endif // BX_PLATFORM_
 
+#if BX_COMPILER_MSVC
+#	include <direct.h> // _getcwd
+#else
+#	include <unistd.h> // getcwd
+#endif // BX_COMPILER_MSVC
+
 namespace bx
 {
 	inline void sleep(uint32_t _ms)
@@ -76,7 +83,7 @@ namespace bx
 		return (pid_t)::syscall(SYS_gettid);
 #elif BX_PLATFORM_IOS || BX_PLATFORM_OSX
 		return (mach_port_t)::pthread_mach_thread_np(pthread_self() );
-#elif BX_PLATFORM_NACL
+#elif BX_PLATFORM_FREEBSD || BX_PLATFORM_NACL
 		// Casting __nc_basic_thread_data*... need better way to do this.
 		return *(uint32_t*)::pthread_self();
 #else
@@ -143,6 +150,24 @@ namespace bx
 #endif // BX_PLATFORM_
 	}
 
+	inline int chdir(const char* _path)
+	{
+#if BX_COMPILER_MSVC
+		return ::_chdir(_path);
+#else
+		return ::chdir(_path);
+#endif // BX_COMPILER_
+	}
+
+	inline char* pwd(char* _buffer, uint32_t _size)
+	{
+#if BX_COMPILER_MSVC
+		return ::_getcwd(_buffer, (int)_size);
+#else
+		return ::getcwd(_buffer, _size);
+#endif // BX_COMPILER_
+	}
+
 } // namespace bx
 
 #endif // BX_OS_H_HEADER_GUARD

+ 11 - 2
include/bx/platform.h

@@ -12,6 +12,7 @@
 
 #define BX_PLATFORM_ANDROID 0
 #define BX_PLATFORM_EMSCRIPTEN 0
+#define BX_PLATFORM_FREEBSD 0
 #define BX_PLATFORM_IOS 0
 #define BX_PLATFORM_LINUX 0
 #define BX_PLATFORM_NACL 0
@@ -89,17 +90,23 @@
 #elif defined(__QNX__)
 #	undef BX_PLATFORM_QNX
 #	define BX_PLATFORM_QNX 1
+#elif defined(__FreeBSD__)
+#	undef BX_PLATFORM_FREEBSD
+#	define BX_PLATFORM_FREEBSD 1
 #else
 #	error "BX_PLATFORM_* is not defined!"
 #endif //
 
-#define BX_PLATFORM_POSIX (BX_PLATFORM_ANDROID \
+#define BX_PLATFORM_POSIX (0 \
+						|| BX_PLATFORM_ANDROID \
 						|| BX_PLATFORM_EMSCRIPTEN \
+						|| BX_PLATFORM_FREEBSD \
 						|| BX_PLATFORM_IOS \
 						|| BX_PLATFORM_LINUX \
 						|| BX_PLATFORM_NACL \
 						|| BX_PLATFORM_OSX \
-						|| BX_PLATFORM_QNX)
+						|| BX_PLATFORM_QNX \
+						)
 
 // http://sourceforge.net/apps/mediawiki/predef/index.php?title=Architectures
 #if defined(__arm__) || (defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP))
@@ -156,6 +163,8 @@
 #	define BX_PLATFORM_NAME "Android"
 #elif BX_PLATFORM_EMSCRIPTEN
 #	define BX_PLATFORM_NAME "asm.js"
+#elif BX_PLATFORM_FREEBSD
+#	define BX_PLATFORM_NAME "FreeBSD"
 #elif BX_PLATFORM_IOS
 #	define BX_PLATFORM_NAME "iOS"
 #elif BX_PLATFORM_LINUX

+ 1 - 1
include/bx/readerwriter.h

@@ -15,7 +15,7 @@
 #if BX_COMPILER_MSVC
 #	define fseeko64 _fseeki64
 #	define ftello64 _ftelli64
-#elif BX_PLATFORM_ANDROID|BX_PLATFORM_IOS|BX_PLATFORM_OSX|BX_PLATFORM_QNX
+#elif BX_PLATFORM_ANDROID || BX_PLATFORM_FREEBSD || BX_PLATFORM_IOS || BX_PLATFORM_OSX || BX_PLATFORM_QNX
 #	define fseeko64 fseeko
 #	define ftello64 ftello
 #endif // BX_

+ 1 - 1
include/bx/timer.h

@@ -12,7 +12,7 @@
 #	include <time.h> // clock, clock_gettime
 #elif BX_PLATFORM_EMSCRIPTEN
 #	include <emscripten.h>
-#elif BX_PLATFORM_NACL || BX_PLATFORM_LINUX || BX_PLATFORM_OSX || BX_PLATFORM_IOS || BX_PLATFORM_QNX
+#elif  BX_PLATFORM_FREEBSD || BX_PLATFORM_LINUX || BX_PLATFORM_NACL || BX_PLATFORM_OSX || BX_PLATFORM_IOS || BX_PLATFORM_QNX
 #	include <sys/time.h> // gettimeofday
 #elif BX_PLATFORM_WINDOWS || BX_PLATFORM_WINRT
 #	include <windows.h>

+ 146 - 0
include/bx/tokenizecmd.h

@@ -0,0 +1,146 @@
+/*
+ * Copyright 2012-2014 Branimir Karadzic. All rights reserved.
+ * License: http://www.opensource.org/licenses/BSD-2-Clause
+ */
+
+#ifndef BX_TOKENIZE_CMD_H_HEADER_GUARD
+#define BX_TOKENIZE_CMD_H_HEADER_GUARD
+
+#include <stdint.h>
+#include <stdio.h>
+#include <ctype.h>
+
+namespace bx
+{
+	// Reference:
+	// http://msdn.microsoft.com/en-us/library/a1y7w461.aspx
+	static inline const char* tokenizeCommandLine(const char* _commandLine, char* _buffer, uint32_t& _bufferSize, int& _argc, char* _argv[], int _maxArgvs, char _term = '\0')
+	{
+		int argc = 0;
+		const char* curr = _commandLine;
+		char* currOut = _buffer;
+		char term = ' ';
+		bool sub = false;
+		
+		enum ParserState
+		{
+			SkipWhitespace,
+			SetTerm,
+			Copy,
+			Escape,
+			End,
+		};
+
+		ParserState state = SkipWhitespace;
+		
+		while ('\0' != *curr
+		&&     _term != *curr
+		&&     argc < _maxArgvs)
+		{
+			switch (state)
+			{
+				case SkipWhitespace:
+					for (; isspace(*curr); ++curr) {}; // skip whitespace
+					state = SetTerm;
+					break;
+					
+				case SetTerm:
+					if ('"' == *curr)
+					{
+						term = '"';
+						++curr; // skip begining quote
+					}
+					else
+					{
+						term = ' ';
+					}
+					
+					_argv[argc] = currOut;
+					++argc;
+					
+					state = Copy;
+					break;
+					
+				case Copy:
+					if ('\\' == *curr)
+					{
+						state = Escape;
+					}
+					else if ('"' == *curr
+						&&  '"' != term)
+					{
+						sub = !sub;
+					}
+					else if (isspace(*curr) && !sub)
+					{
+						state = End;
+					}
+					else if (term != *curr || sub)
+					{
+						*currOut = *curr;
+						++currOut;
+					}
+					else
+					{
+						state = End;
+					}
+					++curr;
+					break;
+					
+				case Escape:
+					{
+						const char* start = --curr;
+						for (; '\\' == *curr; ++curr) {};
+
+						if ('"' != *curr)
+						{
+							int count = (int)(curr-start);
+
+							curr = start;
+							for (int ii = 0; ii < count; ++ii)
+							{
+								*currOut = *curr;
+								++currOut;
+								++curr;
+							}
+						}
+						else
+						{
+							curr = start+1;
+							*currOut = *curr;
+							++currOut;
+							++curr;
+						}
+					}
+					state = Copy;
+					break;
+					
+				case End:
+					*currOut = '\0';
+					++currOut;
+					state = SkipWhitespace;
+					break;
+			}
+		}
+		
+		*currOut = '\0';
+		if (0 < argc
+		&&  '\0' == _argv[argc-1][0])
+		{
+			--argc;
+		}
+
+		_bufferSize = (uint32_t)(currOut - _buffer);
+		_argc = argc;
+
+		if ('\0' != *curr)
+		{
+			++curr;
+		}
+
+		return curr;
+	}
+
+} // namespace bx
+
+#endif // TOKENIZE_CMD_H_HEADER_GUARD

+ 8 - 0
include/bx/uint32_t.h

@@ -263,6 +263,14 @@ namespace bx
 		return _a > _b ? _a : _b;
 	}
 
+	inline uint32_t uint32_clamp(uint32_t _a, uint32_t _min, uint32_t _max)
+	{
+		const uint32_t tmp    = uint32_max(_a, _min);
+		const uint32_t result = uint32_min(tmp, _max);
+
+		return result;
+	}
+
 	inline uint32_t uint32_incwrap(uint32_t _val, uint32_t _min, uint32_t _max)
 	{
 		const uint32_t inc          = uint32_inc(_val);

+ 1 - 0
include/compat/freebsd/alloca.h

@@ -0,0 +1 @@
+#include <stdlib.h>

+ 1 - 0
include/compat/freebsd/malloc.h

@@ -0,0 +1 @@
+#include <stdlib.h>

+ 1 - 0
include/compat/osx/malloc.h

@@ -1 +1,2 @@
 #include <malloc/malloc.h>
+#include <alloca.h>

+ 2 - 0
premake/premake4.lua

@@ -90,3 +90,5 @@ project "bx.test"
 		}
 
 	configuration {}
+
+	strip()

+ 13 - 0
premake/toolchain.lua

@@ -17,6 +17,7 @@ function toolchain(_buildDir, _libDir)
 			{ "android-mips", "Android - MIPS" },
 			{ "android-x86", "Android - x86" },
 			{ "asmjs", "Emscripten/asm.js" },
+			{ "freebsd", "FreeBSD" },
 			{ "linux-gcc", "Linux (GCC compiler)" },
 			{ "linux-clang", "Linux (Clang compiler)" },
 			{ "mingw", "MinGW" },
@@ -98,6 +99,10 @@ function toolchain(_buildDir, _libDir)
 			location (_buildDir .. "projects/" .. _ACTION .. "-asmjs")
 		end
 
+		if "freebsd" == _OPTIONS["gcc"] then
+			location (_buildDir .. "projects/" .. _ACTION .. "-freebsd")
+		end
+
 		if "linux-gcc" == _OPTIONS["gcc"] then
 			location (_buildDir .. "projects/" .. _ACTION .. "-linux")
 		end
@@ -484,6 +489,14 @@ function toolchain(_buildDir, _libDir)
 			"-Wno-warn-absolute-paths",
 		}
 
+	configuration { "freebsd" }
+		targetdir (_buildDir .. "freebsd" .. "/bin")
+		objdir (_buildDir .. "freebsd" .. "/obj")
+		libdirs { _libDir .. "lib/freebsd" }
+		includedirs { 
+			bxDir .. "include/compat/freebsd",
+		}
+
 	configuration { "nacl or nacl-arm or pnacl" }
 		includedirs { 
 			"$(NACL_SDK_ROOT)/include",

+ 1 - 1
premake/unittest++.lua

@@ -29,7 +29,7 @@ project "UnitTest++"
 		"../3rdparty/UnitTest++/src/*.h",
 	}
 
-	configuration { "linux or osx or android-*" }
+	configuration { "linux or osx or android-* or *nacl*" }
 		files {
 			"../3rdparty/UnitTest++/src/Posix/**.cpp",
 			"../3rdparty/UnitTest++/src/Posix/**.h",

+ 1 - 1
tests/float4_t.cpp

@@ -1,5 +1,5 @@
 /*
- * Copyright 2010-2013 Branimir Karadzic. All rights reserved.
+ * Copyright 2010-2014 Branimir Karadzic. All rights reserved.
  * License: http://www.opensource.org/licenses/BSD-2-Clause
  */
 

+ 20 - 1
tests/main.cpp

@@ -38,12 +38,31 @@ int runAllTests()
 }
 
 #if BX_PLATFORM_ANDROID
-#include <android/native_activity.h>
+#	include <android/native_activity.h>
 
 void ANativeActivity_onCreate(ANativeActivity*, void*, size_t)
 {
 	exit(runAllTests() );
 }
+#elif BX_PLATFORM_NACL
+#	include <ppapi/c/pp_errors.h>
+#	include <ppapi/c/ppp.h>
+
+PP_EXPORT const void* PPP_GetInterface(const char* /*_name*/)
+{
+	return NULL;
+}
+
+PP_EXPORT int32_t PPP_InitializeModule(PP_Module /*_module*/, PPB_GetInterface /*_interface*/)
+{
+	DBG("PPAPI version: %d", PPAPI_RELEASE);
+	runAllTests();
+	return PP_ERROR_NOINTERFACE;
+}
+
+PP_EXPORT void PPP_ShutdownModule()
+{
+}
 #else
 int main()
 {

+ 74 - 0
tests/tokenizecmd.cpp

@@ -0,0 +1,74 @@
+/*
+ * Copyright 2012-2014 Branimir Karadzic. All rights reserved.
+ * License: http://www.opensource.org/licenses/BSD-2-Clause
+ */
+
+#include "test.h"
+#include <bx/tokenizecmd.h>
+#include <string.h>
+
+TEST(tokenizeCommandLine)
+{
+#if 0
+	const char* input[] =
+	{
+		"       ",
+		"\\",
+//		"\"a b c\" d e",
+		"\"ab\\\"c\" \"\\\\\" d",
+		"a\\\\\\b d\"e f\"g h",
+		"a\\\\\\\"b c d",
+		"a\\\\\\\\\"b c\" d e",
+	};
+
+	const int expected_argc[] =
+	{
+		0,
+		0,
+//		3,
+		3,
+		3,
+		3,
+		3
+	};
+
+	const char* expected_results[] =
+	{
+		"a b c", "d", "e",
+		"ab\"c", "\\", "d",
+		"a\\\\\\b", "de fg", "h",
+		"a\\\"b", "c", "d",
+		"a\\\\b c", "d", "e",
+	};
+
+	const char** expected_argv[] =
+	{
+		NULL,
+		NULL,
+//		&expected_results[0],
+		&expected_results[3],
+		&expected_results[6],
+		&expected_results[9],
+		&expected_results[12],
+	};
+
+	for (uint32_t ii = 0; ii < BX_COUNTOF(exptected_argv); ++ii)
+	{
+		printf("x\n");
+		char commandLine[1024];
+		uint32_t size = BX_COUNTOF(commandLine);
+		char* argv[50];
+		int32_t argc;
+		bx::tokenizeCommandLine(input[ii], commandLine, size, argc, argv, BX_COUNTOF(argv) );
+		printf("\n%d (%d): %s %s\n", ii, argc, input[ii], expected_argc[ii] == argc ? "" : "FAILED!");
+		for (uint32_t jj = 0; jj < argc; ++jj)
+		{
+			printf("\t%d: {%s} %s\n"
+					, jj
+					, argv[jj]
+					, jj < argc ? (0==strcmp(argv[jj], expected_argv[ii][jj]) ? "" : "FAILED!") : "FAILED!"
+					);
+		}
+	}
+#endif // 0
+}