Переглянути джерело

Merge branch 'master' into renderer-evo

Conflicts:
	engine/Device.cpp
	engine/renderers/gl/egl/GLContext.cpp
	engine/renderers/gles/GLESRenderer.cpp
Daniele Bartolini 12 роки тому
батько
коміт
798a6be9a1
37 змінених файлів з 1056 додано та 552 видалено
  1. 1 3
      engine/Android.mk
  2. 4 3
      engine/CMakeLists.txt
  3. 37 16
      engine/Device.cpp
  4. 10 0
      engine/Device.h
  5. 94 0
      engine/EventBuffer.cpp
  6. 75 0
      engine/EventBuffer.h
  7. 38 31
      engine/input/InputManager.cpp
  8. 5 39
      engine/os/OS.cpp
  9. 3 38
      engine/os/OS.h
  10. 59 29
      engine/os/OsEvents.h
  11. 46 6
      engine/os/android/AndroidDevice.cpp
  12. 14 16
      engine/os/android/AndroidOS.cpp
  13. 2 2
      engine/os/android/ApkFilesystem.cpp
  14. 18 21
      engine/os/android/OsWindow.cpp
  15. 1 2
      engine/os/android/OsWindow.h
  16. 12 40
      engine/os/android/java/CrownActivity.java
  17. 0 0
      engine/os/android/java/CrownEnum.java
  18. 19 10
      engine/os/android/java/CrownLib.java
  19. 31 23
      engine/os/android/java/CrownMainThread.java
  20. 2 2
      engine/os/android/java/CrownSensor.java
  21. 61 17
      engine/os/android/java/CrownSurfaceView.java
  22. 4 5
      engine/os/android/java/CrownTouch.java
  23. 19 18
      engine/os/linux/OsWindow.cpp
  24. 35 4
      engine/os/linux/main.cpp
  25. 35 0
      engine/os/posix/Cond.h
  26. 36 0
      engine/os/posix/Mutex.h
  27. 56 12
      engine/os/posix/Semaphore.h
  28. 0 125
      engine/os/posix/Thread.cpp
  29. 113 45
      engine/os/posix/Thread.h
  30. 72 33
      engine/renderers/gl/egl/GLContext.cpp
  31. 4 7
      engine/renderers/gl/egl/GLContext.h
  32. 2 2
      engine/resource/ResourceLoader.cpp
  33. 20 1
      engine/resource/ResourceLoader.h
  34. 6 1
      engine/tests/CMakeLists.txt
  35. 90 0
      engine/tests/events.cpp
  36. 31 0
      engine/tests/threads.cpp
  37. 1 1
      utils/crown-android.rb

+ 1 - 3
engine/Android.mk

@@ -69,9 +69,6 @@ LOCAL_SRC_FILES :=\
 	os/android/ApkFile.cpp\
 	os/android/ApkFilesystem.cpp\
 	os/posix/OsFile.cpp\
-	os/posix/Thread.cpp\
-	os/posix/Mutex.cpp\
-	os/posix/Cond.cpp\
 	os/posix/TCPSocket.cpp\
 	os/posix/UDPSocket.cpp\
 \
@@ -109,6 +106,7 @@ LOCAL_SRC_FILES :=\
 	Device.cpp\
 	FPSSystem.cpp\
 	ConsoleServer.cpp\
+	EventBuffer.cpp\
 \
 
 LOCAL_C_INCLUDES	:=\

+ 4 - 3
engine/CMakeLists.txt

@@ -66,6 +66,7 @@ set (CROWN_INCLUDES
 set (SRC
 	Camera.cpp
 	Device.cpp
+	EventBuffer.cpp
 	ConsoleServer.cpp
 	FPSSystem.cpp
 )
@@ -75,6 +76,7 @@ set (HEADERS
 	Config.h
 	Crown.h
 	Device.h
+	EventBuffer.h
 	ConsoleServer.h
 	FPSSystem.h
 )
@@ -303,6 +305,7 @@ set (OS_SRC
 set (OS_HEADERS
 	os/OS.h
 	os/NetAddress.h
+	os/OsEvents.h
 )
 
 set (LUA_SRC
@@ -366,6 +369,7 @@ if (LINUX)
 		os/linux/Thread.h
 		os/linux/Mutex.h
 		os/linux/Cond.h
+		os/posix/Semaphore.h
 	)
 
 	list (APPEND OS_SRC
@@ -374,9 +378,6 @@ if (LINUX)
 		os/posix/TCPSocket.cpp
 		os/posix/UDPSocket.cpp	
 		os/posix/OsFile.cpp
-		os/posix/Thread.cpp
-		os/posix/Mutex.cpp
-		os/posix/Cond.cpp
 	)
 
 	list (APPEND RENDERERS_SRC

+ 37 - 16
engine/Device.cpp

@@ -54,6 +54,7 @@ OTHER DEALINGS IN THE SOFTWARE.
 #include "Bundle.h"
 #include "TempAllocator.h"
 #include "ResourcePackage.h"
+#include "EventBuffer.h"
 
 #if defined(LINUX) || defined(WINDOWS)
 	#include "BundleCompiler.h"
@@ -82,6 +83,7 @@ Device::Device() :
 	m_is_init(false),
 	m_is_running(false),
 	m_is_paused(false),
+	m_is_really_paused(false),
 
 	m_frame_count(0),
 
@@ -99,7 +101,9 @@ Device::Device() :
 	m_resource_manager(NULL),
 	m_resource_bundle(NULL),
 
-	m_console_server(NULL)
+	m_console_server(NULL),
+
+	m_renderer_init_request(false)
 {
 	// Bundle dir is current dir by default.
 	string::strncpy(m_bundle_dir, os::get_cwd(), MAX_PATH_LENGTH);
@@ -142,6 +146,14 @@ bool Device::init(int argc, char** argv)
 		}
 	#endif
 
+	init();
+
+	return true;
+}
+
+//-----------------------------------------------------------------------------
+void Device::init()
+{
 	// Initialize
 	Log::i("Initializing Crown Engine %d.%d.%d...", CROWN_VERSION_MAJOR, CROWN_VERSION_MINOR, CROWN_VERSION_MICRO);
 
@@ -178,7 +190,8 @@ bool Device::init(int argc, char** argv)
 	m_input_manager = CE_NEW(m_allocator, InputManager)();
 	Log::d("Input manager created.");
 
-	m_window = CE_NEW(m_allocator, OsWindow)(m_preferred_window_width, m_preferred_window_height, m_parent_window_handle);
+	// default_allocator, maybe it needs fix
+	m_window = CE_NEW(default_allocator(), OsWindow)(m_preferred_window_width, m_preferred_window_height, m_parent_window_handle);
 
 	CE_ASSERT(m_window != NULL, "Unable to create the window");
 
@@ -190,6 +203,7 @@ bool Device::init(int argc, char** argv)
 	m_renderer = CE_NEW(default_allocator(), Renderer)(m_allocator);
 	CE_ASSERT_NOT_NULL(m_renderer);
 	m_renderer->init();
+	m_renderer_init_request = false;
 	Log::d("Renderer created.");
 
 	// Create debug renderer
@@ -229,8 +243,6 @@ bool Device::init(int argc, char** argv)
 		stop();
 		shutdown();
 	}
-
-	return true;
 }
 
 //-----------------------------------------------------------------------------
@@ -279,7 +291,7 @@ void Device::shutdown()
 	Log::i("Releasing Window...");
 	if (m_window)
 	{
-		CE_DELETE(m_allocator, m_window);
+		CE_DELETE(default_allocator(), m_window);
 	}
 
 	Log::i("Releasing ResourceManager...");
@@ -318,6 +330,12 @@ bool Device::is_init() const
 	return m_is_init;
 }
 
+//-----------------------------------------------------------------------------
+bool Device::is_paused() const
+{
+	return m_is_paused;
+}
+
 //-----------------------------------------------------------------------------
 Filesystem* Device::filesystem()
 {
@@ -409,6 +427,7 @@ void Device::stop()
 void Device::pause()
 {
 	m_is_paused = true;
+
 	Log::d("Engine paused");
 }
 
@@ -416,6 +435,8 @@ void Device::pause()
 void Device::unpause()
 {
 	m_is_paused = false;
+	m_is_really_paused = false;
+
 	Log::d("Engine unpaused");
 }
 
@@ -451,26 +472,26 @@ void Device::frame(cb callback)
 	m_last_time = m_current_time;
 	m_time_since_start += m_last_delta_time;
 
-	m_resource_manager->poll_resource_loader();
-
-	m_window->frame();
-	m_input_manager->frame(frame_count());
-
 	if (!m_is_paused)
 	{
+		m_resource_manager->poll_resource_loader();
+
+		m_window->frame();
+		m_input_manager->frame(frame_count());
+
 		if (!m_lua_environment->call_global("frame", 1, ARGUMENT_FLOAT, last_delta_time()))
 		{
 			pause();
 		}
-	}
-
-	m_debug_renderer->draw_all();
 
-	callback(m_last_delta_time);
-
-	m_renderer->frame();
+		m_debug_renderer->draw_all();
+		callback(m_last_delta_time);
+		m_renderer->frame();
+	}
 
 	m_frame_count++;
+
+	os_event_buffer()->clear();
 }
 
 //-----------------------------------------------------------------------------

+ 10 - 0
engine/Device.h

@@ -79,6 +79,9 @@ public:
 	/// Returns whether the engine is correctly initialized
 	bool					is_init() const;
 
+	/// Returns wheter the engine is paused
+	bool 					is_paused() const;
+
 	/// Return the number of frames rendered from the first
 	/// call to Device::start()
 	uint64_t				frame_count() const;
@@ -136,6 +139,7 @@ public:
 
 private:
 
+	void					init();
 	void					parse_command_line(int argc, char** argv);
 	void					check_preferred_settings();
 	void					read_engine_settings();
@@ -164,6 +168,8 @@ private:
 	bool					m_is_running	: 1;
 	bool					m_is_paused		: 1;
 
+	bool 					m_is_really_paused :1;
+
 	uint64_t				m_frame_count;
 
 	uint64_t				m_last_time;
@@ -188,11 +194,15 @@ private:
 	// Debug subsystems
 	ConsoleServer*			m_console_server;
 
+	bool 					m_renderer_init_request;
+
 private:
 
 	// Disable copying
 	Device(const Device&);
 	Device& operator=(const Device&);
+
+	friend class MainThread;
 };
 
 CE_EXPORT Device* device();

+ 94 - 0
engine/EventBuffer.cpp

@@ -0,0 +1,94 @@
+#include "EventBuffer.h"
+#include "Log.h"
+
+namespace crown
+{
+
+//-----------------------------------------------------------------------------
+EventBuffer::EventBuffer() : m_size(0), m_read(0)
+{
+}
+
+//-----------------------------------------------------------------------------
+void EventBuffer::push_event(uint32_t event_type, void* event_data, size_t event_size)
+{
+	if (m_size + sizeof(event_type) + sizeof(event_size) + event_size > MAX_OS_EVENT_BUFFER_SIZE)
+	{
+		flush();
+	}
+
+	char* cur = m_buffer + m_size;
+
+	*(uint32_t*) cur = event_type;
+	*(size_t*) (cur + sizeof(event_type)) = event_size;
+	memcpy(cur + sizeof(event_type) + sizeof(event_size), event_data, event_size);
+
+	m_size += sizeof(event_type) + sizeof(event_size) + event_size;
+}
+
+//-----------------------------------------------------------------------------
+void EventBuffer::push_event_buffer(char* event_buffer, size_t buffer_size)
+{
+	if (m_size + buffer_size > MAX_OS_EVENT_BUFFER_SIZE)
+	{
+		flush();
+	}
+
+	char* cur = m_buffer + m_size;
+
+	memcpy(cur, event_buffer, buffer_size);
+
+	m_size += buffer_size;
+}
+
+
+//-----------------------------------------------------------------------------
+void* EventBuffer::get_next_event(uint32_t& event_type, size_t& event_size)
+{
+	if (m_read < m_size)
+	{
+		char* cur = m_buffer + m_read;
+
+		// Saves type
+		event_type = *(uint32_t*) cur;
+		// Saves size
+		event_size = *(size_t*)(cur + sizeof(uint32_t));
+
+		// Set read to next event
+		m_read += sizeof(size_t) + sizeof(uint32_t) + event_size;
+
+		return cur + sizeof(size_t) + sizeof(uint32_t);
+	}
+
+	m_read = 0;
+
+	return NULL;
+}
+
+//-----------------------------------------------------------------------------
+void EventBuffer::clear()
+{
+	m_size = 0;
+	m_read = 0;
+}
+
+//-----------------------------------------------------------------------------
+void EventBuffer::flush()
+{
+	m_size = 0;
+	m_read = 0;
+}
+
+//-----------------------------------------------------------------------------
+size_t EventBuffer::size() const
+{
+	return m_size;
+}
+
+//-----------------------------------------------------------------------------
+char* EventBuffer::buffer()
+{
+	return m_buffer;
+}
+
+} // namespace crown

+ 75 - 0
engine/EventBuffer.h

@@ -0,0 +1,75 @@
+/*
+Copyright (c) 2013 Daniele Bartolini, Michele Rossi
+Copyright (c) 2012 Daniele Bartolini, Simone Boscaratto
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#pragma once
+
+#include <cstring>
+
+#include "Types.h"
+
+#define MAX_OS_EVENT_BUFFER_SIZE 1024
+
+namespace crown
+{
+
+
+///	__EventBuffer__ is a global buffer used for storing events.
+///	Each subsystem can read its relative events and modifies its behaviour consequently.
+///
+/// [type #0][size #0][data #0] ... [type #n][size #n][data #n]
+class EventBuffer
+{
+
+public:
+	/// Constructor
+				EventBuffer();
+
+	/// Pushes an @a event_data of size @a event_size with type @a event_type 
+	void		push_event(uint32_t event_type, void* event_data, size_t event_size);
+	/// Pushes an entire @a event_buffer of size @a buffer_size
+	void		push_event_buffer(char* event_buffer, size_t buffer_size);
+	/// Retrieves the @a event_type and @a event_size of next os event
+	void*		get_next_event(uint32_t& event_type, size_t& event_size);
+
+	/// Clears entire os buffer
+	void		clear();
+	/// Flushes entire os buffer
+	void		flush();
+
+	/// Returns buffer's size
+	size_t		size() const;
+	/// Return buffer
+	char*		buffer();
+
+public:
+
+	size_t		m_size;
+	char		m_buffer[MAX_OS_EVENT_BUFFER_SIZE];
+
+	uint32_t	m_read;
+};
+
+} // namespace crown

+ 38 - 31
engine/input/InputManager.cpp

@@ -27,6 +27,8 @@ OTHER DEALINGS IN THE SOFTWARE.
 #include "InputManager.h"
 #include "OS.h"
 #include "Log.h"
+#include "EventBuffer.h"
+#include "OsEvents.h"
 
 namespace crown
 {
@@ -98,7 +100,9 @@ EventDispatcher* InputManager::get_event_dispatcher()
 //-----------------------------------------------------------------------------
 void InputManager::frame(uint64_t frame_count)
 {
-	OsEvent event;
+	void* event;
+	uint32_t event_type;
+	size_t event_size;
 
 	// Update input devices
 	m_keyboard.m_current_frame = frame_count;
@@ -106,9 +110,12 @@ void InputManager::frame(uint64_t frame_count)
 
 	while (1)
 	{
-		event = pop_event();
+		if ((event = os_event_buffer()->get_next_event(event_type, event_size)) == NULL)
+		{
+			break;
+		}
 
-		switch (event.type)
+		switch (event_type)
 		{
 			case OSET_NONE:
 			{
@@ -118,12 +125,12 @@ void InputManager::frame(uint64_t frame_count)
 			case OSET_BUTTON_RELEASE:
 			{
 				MouseEvent mouse_event;
-				mouse_event.x = event.data_a.int_value;
-				mouse_event.y = event.data_b.int_value;
-				mouse_event.button = event.data_c.int_value == 0 ? MB_LEFT : event.data_c.int_value == 1 ? MB_MIDDLE : MB_RIGHT;
+				mouse_event.x = ((OsMouseEvent*)event)->x;
+				mouse_event.y = ((OsMouseEvent*)event)->y;
+				mouse_event.button = ((OsMouseEvent*)event)->button == 0 ? MB_LEFT : ((OsMouseEvent*)event)->button == 1 ? MB_MIDDLE : MB_RIGHT;
 				mouse_event.wheel = 0.0f;
 
-				if (event.type == OSET_BUTTON_PRESS)
+				if (event_type == OSET_BUTTON_PRESS)
 				{
 					m_mouse.update(frame_count, mouse_event.button, true);
 					m_event_dispatcher.button_pressed(mouse_event);
@@ -140,12 +147,12 @@ void InputManager::frame(uint64_t frame_count)
 			case OSET_KEY_RELEASE:
 			{
 				KeyboardEvent keyboard_event;
-				keyboard_event.key = (KeyCode)event.data_a.int_value;
-				keyboard_event.modifier = (uint8_t)event.data_b.int_value;
+				keyboard_event.key = (KeyCode) ((OsKeyboardEvent*)event)->key;
+				keyboard_event.modifier = (uint8_t) ((OsKeyboardEvent*)event)->modifier;
 
 				m_keyboard.m_modifier = keyboard_event.modifier;
 
-				if (event.type == OSET_KEY_PRESS)
+				if (event_type == OSET_KEY_PRESS)
 				{
 					m_keyboard.update(frame_count, keyboard_event.key, true);
 					m_event_dispatcher.key_pressed(keyboard_event);
@@ -162,9 +169,9 @@ void InputManager::frame(uint64_t frame_count)
 			case OSET_TOUCH_UP:
 			{
 				TouchEvent touch_event;
-				touch_event.pointer_id = event.data_a.int_value;
-				touch_event.x = event.data_b.int_value;
-				touch_event.y = event.data_c.int_value;
+				touch_event.pointer_id = ((OsTouchEvent*)event)->pointer_id;
+				touch_event.x = ((OsTouchEvent*)event)->x;
+				touch_event.y = ((OsTouchEvent*)event)->y;
 
 				m_touch.m_pointers[touch_event.pointer_id].x = touch_event.x;
 				m_touch.m_pointers[touch_event.pointer_id].y = touch_event.y;
@@ -173,7 +180,7 @@ void InputManager::frame(uint64_t frame_count)
 				m_touch.m_pointers[touch_event.pointer_id].relative_x = 0.0f;
 				m_touch.m_pointers[touch_event.pointer_id].relative_y = 0.0f;
 
-				if (event.type == OSET_TOUCH_DOWN)
+				if (event_type == OSET_TOUCH_DOWN)
 				{
 					m_touch.m_pointers[touch_event.pointer_id].up = false;
 					m_event_dispatcher.touch_down(touch_event);
@@ -189,9 +196,9 @@ void InputManager::frame(uint64_t frame_count)
 			case OSET_TOUCH_MOVE:
 			{
 				TouchEvent touch_event;
-				touch_event.pointer_id = event.data_a.int_value;
-				touch_event.x = event.data_b.int_value;
-				touch_event.y = event.data_c.int_value;
+				touch_event.pointer_id = ((OsTouchEvent*)event)->pointer_id;
+				touch_event.x = ((OsTouchEvent*)event)->x;
+				touch_event.y = ((OsTouchEvent*)event)->y;
 
 				m_touch.m_pointers[touch_event.pointer_id].x = touch_event.x;
 				m_touch.m_pointers[touch_event.pointer_id].y = touch_event.y;
@@ -204,20 +211,20 @@ void InputManager::frame(uint64_t frame_count)
 
 				break;
 			}
-			case OSET_ACCELEROMETER:
-			{
-				AccelerometerEvent sensor_event;
-				sensor_event.x = event.data_a.float_value;
-				sensor_event.y = event.data_b.float_value;
-				sensor_event.z = event.data_c.float_value;
-
-				m_accelerometer.m_orientation.x = sensor_event.x;
-				m_accelerometer.m_orientation.y = sensor_event.y;
-				m_accelerometer.m_orientation.z = sensor_event.z;
-
-				m_event_dispatcher.accelerometer_changed(sensor_event);
-				break;
-			}
+			// case OSET_ACCELEROMETER:
+			// {
+			// 	AccelerometerEvent sensor_event;
+			// 	sensor_event.x = event.data_a.float_value;
+			// 	sensor_event.y = event.data_b.float_value;
+			// 	sensor_event.z = event.data_c.float_value;
+
+			// 	m_accelerometer.m_orientation.x = sensor_event.x;
+			// 	m_accelerometer.m_orientation.y = sensor_event.y;
+			// 	m_accelerometer.m_orientation.z = sensor_event.z;
+
+			// 	m_event_dispatcher.accelerometer_changed(sensor_event);
+			// 	break;
+			// }
 			default:
 			{
 				break;

+ 5 - 39
engine/os/OS.cpp

@@ -1,4 +1,5 @@
 /*
+Copyright (c) 2013 Daniele Bartolini, Michele Rossi
 Copyright (c) 2012 Daniele Bartolini, Simone Boscaratto
 
 Permission is hereby granted, free of charge, to any person
@@ -28,46 +29,11 @@ OTHER DEALINGS IN THE SOFTWARE.
 namespace crown
 {
 
-static const size_t		MAX_EVENTS = 512;
-static OsEvent			event_queue[MAX_EVENTS];
-static uint32_t			event_queue_head = 0;
-static uint32_t			event_queue_tail = 0;
+EventBuffer g_os_event_buffer;
 
-//-----------------------------------------------------------------------------
-void push_event(OsEventType type, OsEventParameter data_a, OsEventParameter data_b, OsEventParameter data_c, OsEventParameter data_d)
+EventBuffer* os_event_buffer()
 {
-	if ((event_queue_tail + 1) % MAX_EVENTS == event_queue_head)
-	{
-		os::printf("OS event queue full!\n");
-		return;
-	}
-
-	OsEvent* event = &event_queue[event_queue_tail];
-	event_queue_tail = (event_queue_tail + 1) % MAX_EVENTS;
-
-	event->type = type;
-	event->data_a = data_a;
-	event->data_b = data_b;
-	event->data_c = data_c;
-	event->data_d = data_d;
+	return &g_os_event_buffer;
 }
 
-//-----------------------------------------------------------------------------
-OsEvent& pop_event()
-{
-	static OsEvent event;
-
-	if (event_queue_head == event_queue_tail)
-	{
-		event.type = OSET_NONE;
-		return event;
-	}
-
-	event = event_queue[event_queue_head];
-	event_queue_head = (event_queue_head + 1) % MAX_EVENTS;
-
-	return event;
-}
-
-} // namespace crown
-
+} // namespace crown

+ 3 - 38
engine/os/OS.h

@@ -32,6 +32,7 @@ OTHER DEALINGS IN THE SOFTWARE.
 #include "Types.h"
 #include "Vector.h"
 #include "DynamicString.h"
+#include "EventBuffer.h"
 
 namespace crown
 {
@@ -155,47 +156,11 @@ void*			lookup_symbol(void* library, const char* name);
 /// @a args[n] is NULL.
 void			execute_process(const char* args[]);
 
-} // namespace os
-
-//-----------------------------------------------------------------------------
-// Events
 //-----------------------------------------------------------------------------
-enum OsEventType
-{
-	OSET_NONE				= 0,
-
-	OSET_KEY_PRESS			= 1,
-	OSET_KEY_RELEASE		= 2,
 
-	OSET_BUTTON_PRESS		= 3,
-	OSET_BUTTON_RELEASE		= 4,
-	OSET_MOTION_NOTIFY		= 5,
-	OSET_TOUCH_DOWN			= 6,
-	OSET_TOUCH_MOVE			= 7,
-	OSET_TOUCH_UP			= 8,
-	OSET_ACCELEROMETER		= 9
-};
-
-union OsEventParameter
-{
-	int32_t int_value;
-	float	float_value;
-};
+} // namespace os
 
-struct OsEvent
-{
-	OsEventType			type;
-	OsEventParameter	data_a;
-	OsEventParameter	data_b;
-	OsEventParameter	data_c;
-	OsEventParameter	data_d;
-};
-
-/// Pushes the event @a type along with its parameters into the os' event queue.
-void			push_event(OsEventType type, OsEventParameter data_a, OsEventParameter data_b, OsEventParameter data_c, OsEventParameter data_d);
-
-/// Returns and pops the first event in the os' event queue.
-OsEvent&		pop_event();
+EventBuffer* 	os_event_buffer();
 
 } // namespace crown
 

+ 59 - 29
engine/os/android/MainThread.java → engine/os/OsEvents.h

@@ -24,35 +24,65 @@ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 OTHER DEALINGS IN THE SOFTWARE.
 */
 
-package crown.android;
+#pragma once
 
-import android.view.SurfaceHolder;
+#include "Types.h"
 
-public class MainThread extends Thread
+namespace crown
 {
-	private SurfaceHolder mHolder;
-	private CrownSurfaceView mView;
-
-	public MainThread(SurfaceHolder holder, CrownSurfaceView view)
-	{
-		super();
-
-		mHolder = holder;
-		mView = view;
-	}
-
-	// This is the classic main() replacement for Android
-	@Override
-	public void run()
-	{
-		CrownLib.setWindow(mHolder.getSurface());
-		CrownLib.init();
-
-		while (CrownLib.isRunning())
-		{
-			CrownLib.frame();
-		}
-
-		CrownLib.shutdown();
-	}
-}
+
+/// __OsEventType__ represents an event fired by the OS
+enum OsEventType
+{
+	OSET_NONE				= 0,
+
+	OSET_KEY_PRESS			= 1,
+	OSET_KEY_RELEASE		= 2,
+
+	OSET_BUTTON_PRESS		= 3,
+	OSET_BUTTON_RELEASE		= 4,
+
+	OSET_MOTION_NOTIFY		= 5,
+	OSET_TOUCH_DOWN			= 6,
+	OSET_TOUCH_MOVE			= 7,
+	OSET_TOUCH_UP			= 8,
+	
+	OSET_ACCELEROMETER		= 9
+};
+
+/// __OsMouseEvent__ represents an event fired by mouse.
+/// It is processed by InputManager.
+struct OsMouseEvent
+{
+	uint32_t button;
+	uint32_t x;
+	uint32_t y;
+};
+
+/// __OsKeyboardEvent__ represents an event fired by keyboard.
+/// it is processed by InputManager.
+struct OsKeyboardEvent
+{
+	uint32_t key;
+	uint32_t modifier;
+};
+
+/// __OsTouchEvent__ represents an event fired by touch screen.
+/// It is processed by InputManager.
+struct OsTouchEvent
+{
+	uint32_t pointer_id;
+	uint32_t x;
+	uint32_t y;
+};
+
+/// __OsAccelerometerEvent__ represents an event fired by accelerometer.
+/// It is processed by InputManager.
+struct OsAccelerometerEvent
+{
+	float x;
+	float y;
+	float z;	
+};
+
+} // namespace crown

+ 46 - 6
engine/os/android/AndroidDevice.cpp

@@ -26,12 +26,14 @@ OTHER DEALINGS IN THE SOFTWARE.
 
 #include <jni.h>
 #include "Device.h"
+#include "Renderer.h"
+#include "Log.h"
 
 namespace crown
 {
 
 //-----------------------------------------------------------------------------
-extern "C" JNIEXPORT void JNICALL Java_crown_android_CrownLib_init(JNIEnv* /*env*/, jobject /*obj*/)
+extern "C" JNIEXPORT void JNICALL Java_crown_android_CrownLib_initDevice(JNIEnv* /*env*/, jobject /*obj*/)
 {
 	const char* argv[] = { "crown-android" };
 
@@ -39,27 +41,65 @@ extern "C" JNIEXPORT void JNICALL Java_crown_android_CrownLib_init(JNIEnv* /*env
 }
 
 //-----------------------------------------------------------------------------
-extern "C" JNIEXPORT void JNICALL Java_crown_android_CrownLib_shutdown(JNIEnv* /*env*/, jobject /*obj*/)
+extern "C" JNIEXPORT void JNICALL Java_crown_android_CrownLib_stopDevice(JNIEnv* /*env*/, jobject /*obj*/)
+{
+	device()->stop();
+}
+
+//-----------------------------------------------------------------------------
+extern "C" JNIEXPORT void JNICALL Java_crown_android_CrownLib_shutdownDevice(JNIEnv* /*env*/, jobject /*obj*/)
 {
 	device()->shutdown();
 }
 
 //-----------------------------------------------------------------------------
-extern "C" JNIEXPORT void JNICALL Java_crown_android_CrownLib_frame(JNIEnv* /*env*/, jobject /*obj*/)
+extern "C" JNIEXPORT void JNICALL Java_crown_android_CrownLib_pauseDevice(JNIEnv* /*env*/, jobject /*obj*/)
 {
-	device()->frame();
+	device()->pause();
+}
+
+//-----------------------------------------------------------------------------
+extern "C" JNIEXPORT void JNICALL Java_crown_android_CrownLib_unpauseDevice(JNIEnv* /*env*/, jobject /*obj*/)
+{
+	device()->unpause();
 }
 
 //-----------------------------------------------------------------------------
-extern "C" JNIEXPORT bool JNICALL Java_crown_android_CrownLib_isInit(JNIEnv* /*env*/, jobject /*obj*/)
+extern "C" JNIEXPORT bool JNICALL Java_crown_android_CrownLib_isDeviceInit(JNIEnv* /*env*/, jobject /*obj*/)
 {
 	return device()->is_init();
 }
 
 //-----------------------------------------------------------------------------
-extern "C" JNIEXPORT bool JNICALL Java_crown_android_CrownLib_isRunning(JNIEnv* /*env*/, jobject /*obj*/)
+extern "C" JNIEXPORT bool JNICALL Java_crown_android_CrownLib_isDeviceRunning(JNIEnv* /*env*/, jobject /*obj*/)
 {
 	return device()->is_running();
 }
 
+//-----------------------------------------------------------------------------
+extern "C" JNIEXPORT bool JNICALL Java_crown_android_CrownLib_isDevicePaused(JNIEnv* /*env*/, jobject /*obj*/)
+{
+	return device()->is_paused();
+}
+
+//-----------------------------------------------------------------------------
+extern "C" JNIEXPORT void JNICALL Java_crown_android_CrownLib_frame(JNIEnv* /*env*/, jobject /*obj*/)
+{
+	device()->frame();
+}
+
+//-----------------------------------------------------------------------------
+extern "C" JNIEXPORT void JNICALL Java_crown_android_CrownLib_initRenderer(JNIEnv* /*env*/, jobject /*obj*/)
+{
+	device()->renderer()->init();
+	Log::i("Renderer initialized");
+}
+
+//-----------------------------------------------------------------------------
+extern "C" JNIEXPORT void JNICALL Java_crown_android_CrownLib_shutdownRenderer(JNIEnv* /*env*/, jobject /*obj*/)
+{
+	device()->renderer()->shutdown();
+	Log::i("Renderer shutdowned");
+}
+
 } // namespace crown

+ 14 - 16
engine/os/android/AndroidOS.cpp

@@ -39,6 +39,7 @@ OTHER DEALINGS IN THE SOFTWARE.
 #include <unistd.h>
 
 #include "OS.h"
+#include "OsEvents.h"
 #include "Assert.h"
 #include "StringUtils.h"
 
@@ -47,7 +48,7 @@ namespace crown
 namespace os
 {
 
-static timespec			base_time;
+static timespec	base_time;
 
 //-----------------------------------------------------------------------------
 void printf(const char* string, ...)
@@ -307,33 +308,30 @@ void execute_process(const char* args[])
 	}
 }
 
-
 } // namespace os
 
 //-----------------------------------------------------------------------------
-extern "C" JNIEXPORT void JNICALL Java_crown_android_CrownLib_pushIntEvent(JNIEnv * /*env*/, jobject /*obj*/, jint type, jint a, jint b, jint c, jint d)
+extern "C" JNIEXPORT void JNICALL Java_crown_android_CrownLib_pushTouchEvent(JNIEnv * /*env*/, jobject /*obj*/, jint type, jint pointer_id, jint x, jint y)
 {	
-	OsEventParameter values[4];
+	OsTouchEvent event;
 
-	values[0].int_value = a;
-	values[1].int_value = b;
-	values[2].int_value = c;
-	values[3].int_value = d;
+	event.pointer_id = pointer_id;
+	event.x = x;
+	event.y = y;
 
-	push_event((OsEventType)type, values[0], values[1], values[2], values[3]);
+	os_event_buffer()->push_event((OsEventType)type, &event, sizeof(OsTouchEvent));
 }
 
 //-----------------------------------------------------------------------------
-extern "C" JNIEXPORT void JNICALL Java_crown_android_CrownLib_pushFloatEvent(JNIEnv * /*env*/, jobject /*obj*/, jint type, jfloat a, jfloat b, jfloat c, jfloat d)
+extern "C" JNIEXPORT void JNICALL Java_crown_android_CrownLib_pushAccelerometerEvent(JNIEnv * /*env*/, jobject /*obj*/, jint type, jfloat x, jfloat y, jfloat z)
 {
-	OsEventParameter values[4];
+	OsAccelerometerEvent event;
 
-	values[0].float_value = a;
-	values[1].float_value = b;
-	values[2].float_value = c;
-	values[3].float_value = d;
+	event.x = x;
+	event.y = y;
+	event.z = z;
 
-	push_event((OsEventType)type, values[0], values[1], values[2], values[3]);
+	os_event_buffer()->push_event((OsEventType)type, &event, sizeof(OsAccelerometerEvent));
 }
 
 } // namespace crown

+ 2 - 2
engine/os/android/ApkFilesystem.cpp

@@ -59,13 +59,13 @@ void ApkFilesystem::close(File* file)
 //-----------------------------------------------------------------------------
 bool ApkFilesystem::is_directory(const char* path)
 {
-	return false;
+	return true;
 }
 
 //-----------------------------------------------------------------------------
 bool ApkFilesystem::is_file(const char* path)
 {
-	return false;
+	return true;
 }
 
 //-----------------------------------------------------------------------------

+ 18 - 21
engine/os/android/OsWindow.cpp

@@ -24,41 +24,31 @@ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 OTHER DEALINGS IN THE SOFTWARE.
 */
 
-#include <android/native_window_jni.h>
-
 #include "OsWindow.h"
 #include "GLContext.h"
 #include "Assert.h"
+#include "Log.h"
 
 namespace crown
 {
 
-static ANativeWindow* window = NULL;
+ANativeWindow* g_android_window = NULL;
 
 //-----------------------------------------------------------------------------
-OsWindow::OsWindow(uint32_t /*width*/, uint32_t /*height*/, uint32_t /*parent*/) :
-	m_window(NULL),
-	m_x(0),
-	m_y(0),
-	m_width(0),
-	m_height(0)
+OsWindow::OsWindow(uint32_t /*width*/, uint32_t /*height*/, uint32_t /*parent*/)
+	: m_x(0), m_y(0), m_width(0), m_height(0)
 {
-	m_window = window;
-
-	m_width = ANativeWindow_getWidth(m_window);
-	m_height = ANativeWindow_getHeight(m_window);
-
-    set_android_window(m_window);
+	m_width = ANativeWindow_getWidth(g_android_window);
+	m_height = ANativeWindow_getHeight(g_android_window);
 }
 
 //-----------------------------------------------------------------------------
 OsWindow::~OsWindow()
 {
-	if (m_window)
+	if (g_android_window)
 	{
-		ANativeWindow_release(m_window);
+		ANativeWindow_release(g_android_window);
 	}
-
 }
 
 //-----------------------------------------------------------------------------
@@ -129,15 +119,22 @@ void OsWindow::set_title(const char* /*title*/)
 //-----------------------------------------------------------------------------
 void OsWindow::frame()
 {
-	// Implemented Java-side
 }
 
 //-----------------------------------------------------------------------------
-extern "C" void Java_crown_android_CrownLib_setWindow(JNIEnv *env, jclass /*clazz*/, jobject surface)
+extern "C" void Java_crown_android_CrownLib_createWindow(JNIEnv *env, jclass /*clazz*/, jobject surface)
 {
     // obtain a native window from a Java surface
 	CE_ASSERT(surface != 0, "Unable to get Android window");
-    window = ANativeWindow_fromSurface(env, surface);
+    g_android_window = ANativeWindow_fromSurface(env, surface);
+    Log::i("Window created");
+}
+
+//-----------------------------------------------------------------------------
+extern "C" void Java_crown_android_CrownLib_destroyWindow(JNIEnv *env, jclass /*clazz*/, jobject surface)
+{
+    ANativeWindow_release(g_android_window);
+    Log::i("Window destroyed");
 }
 
 } // namespace crown

+ 1 - 2
engine/os/android/OsWindow.h

@@ -28,6 +28,7 @@ OTHER DEALINGS IN THE SOFTWARE.
 
 #include <sys/types.h>
 #include <android/native_window.h>
+#include <android/native_window_jni.h>
 
 namespace crown
 {
@@ -81,8 +82,6 @@ public:
 
 private:
 
-	ANativeWindow*	m_window;
-
 	uint32_t		m_x;
 	uint32_t		m_y;
 	uint32_t		m_width;

+ 12 - 40
engine/os/android/CrownActivity.java → engine/os/android/java/CrownActivity.java

@@ -38,6 +38,7 @@ import android.hardware.SensorManager;
 import android.content.Context;
 import android.widget.Toast;
 import android.content.res.AssetManager;
+import android.view.View;
 import android.view.Surface;
 import android.view.SurfaceView;
 import android.view.SurfaceHolder;
@@ -49,9 +50,8 @@ import crown.android.CrownEnum;
 */
 public class CrownActivity extends Activity
 {
-
 	// Debug
-	public static String TAG = "CrownActivity";
+	public static String TAG = "crown";
 
 	// Resource attributes
     static AssetManager 		mAssetManager;
@@ -60,8 +60,8 @@ public class CrownActivity extends Activity
 	private CrownTouch 			mTouch;
 	private CrownSensor			mSensor;
 
-	// Graphic attributes
-	static CrownSurfaceView		mWindow;
+	private CrownSurfaceView 	mView;
+
 
 //-----------------------------------------------------------------------------
     public void onCreate(Bundle savedInstanceState)
@@ -73,26 +73,15 @@ public class CrownActivity extends Activity
 		CrownLib.initAssetManager(mAssetManager);
 
 		// init Native Window
-        mWindow = new CrownSurfaceView(this);
-        setContentView(mWindow);
+		mView = new CrownSurfaceView(this);
+        setContentView(mView);
 
 		// Init Input
 		mTouch = new CrownTouch(this);
 		mSensor = new CrownSensor(this);
-    }
-
-//-----------------------------------------------------------------------------
-	public void onStart()
-	{
-		super.onStart();
 
-	}
-
-//-----------------------------------------------------------------------------
-	public void onRestart()
-	{
-		super.onRestart();
-	}
+		Log.i(TAG, "Crown Activity created");
+    }
 
 //-----------------------------------------------------------------------------
 	public void onResume()
@@ -100,31 +89,20 @@ public class CrownActivity extends Activity
 		super.onResume();
 		
 		// init accelerometer
-		if (!mSensor.startListening(this))
-		{
-			finish();
-		}
+		mSensor.startListening(this);
+
+		Log.i(TAG, "Crown Activity resumed");
 	}
 
 //-----------------------------------------------------------------------------
 	public void onPause()
 	{
 		super.onPause();
-	}
-
-//-----------------------------------------------------------------------------
-	public void onStop()
-	{
-		super.onStop();
 
 		// stop accelerometer
 		mSensor.stopListening();
-	}
 
-//-----------------------------------------------------------------------------
-	public void onDestroy()
-	{
-		super.onDestroy();
+		Log.i(TAG, "Crown Activity paused");
 	}
 
 //-----------------------------------------------------------------------------
@@ -133,10 +111,4 @@ public class CrownActivity extends Activity
 		mTouch.onTouch(event);
         return super.onTouchEvent(event);
 	}
-
-//-----------------------------------------------------------------------------
-	public boolean hasMultiTouchSupport(Context context)
-	{
-		return context.getPackageManager().hasSystemFeature("android.hardware.touchscreen.multitouch");
-	}
 }

+ 0 - 0
engine/os/android/CrownEnum.java → engine/os/android/java/CrownEnum.java


+ 19 - 10
engine/os/android/CrownLib.java → engine/os/android/java/CrownLib.java

@@ -38,20 +38,29 @@ public class CrownLib
 	}
 	
 	// Device functions
-	public static native void 		init();
+	public static native void 		initDevice();
+	public static native void		pauseDevice();
+	public static native void		unpauseDevice();
+	public static native void		stopDevice();
+
+	public static native boolean 	isDeviceInit();
+	public static native boolean	isDeviceRunning();
+	public static native boolean	isDevicePaused();
+
 	public static native void 		frame();
-	public static native void 		shutdown();
-	public static native boolean 	isInit();
-	public static native boolean	isRunning();
 
 	// AssetManager functions
 	public static native void 		initAssetManager(AssetManager assetManager);
 
-	// InputManager functions
-	public static native void 		pushIntEvent(int type, int a, int b, int c, int d);
-	public static native void 		pushFloatEvent(int type, float a, float b, float c, float d);
-
 	// Window functions
-	public static native void		setWindow(Surface window);
-	public static native void 		setDisplaySize(int width, int height);
+	public static native void		createWindow(Surface window);
+	public static native void		destroyWindow();
+
+	// Renderer functions
+	public static native void		initRenderer();
+	public static native void		shutdownRenderer();
+
+	// InputManager functions
+	public static native void 		pushTouchEvent(int type, int pointer_id, int x, int y);
+	public static native void 		pushAccelerometerEvent(int type, float x, float y, float z);	
 }

+ 31 - 23
engine/os/posix/Cond.cpp → engine/os/android/java/CrownMainThread.java

@@ -24,37 +24,45 @@ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 OTHER DEALINGS IN THE SOFTWARE.
 */
 
-#include <string.h>
+package crown.android;
 
-#include "Cond.h"
+import android.util.Log;
+import android.view.SurfaceHolder;
 
-namespace crown
+///
+public class CrownMainThread extends Thread
 {
+	private SurfaceHolder mSurfaceHolder;
 
-//-----------------------------------------------------------------------------
-Cond::Cond()
-{
-	memset(&m_cond, 0, sizeof(pthread_cond_t));
+	private boolean mPaused;
 
-	pthread_cond_init(&m_cond, NULL);
-}
 
 //-----------------------------------------------------------------------------
-Cond::~Cond()
-{
-	pthread_cond_destroy(&m_cond);
-}
+	public CrownMainThread(SurfaceHolder holder)
+	{
+		super();
+		mSurfaceHolder = holder;
+	}
 
 //-----------------------------------------------------------------------------
-void Cond::signal()
-{
-	pthread_cond_signal(&m_cond);
-}
+	@Override
+	public void run()
+	{
+		CrownLib.createWindow(mSurfaceHolder.getSurface());
 
-//-----------------------------------------------------------------------------
-void Cond::wait(Mutex& mutex)
-{
-	pthread_cond_wait(&m_cond, &(mutex.m_mutex));
-}
+		if (!CrownLib.isDeviceInit())
+		{
+			CrownLib.initDevice();
+		}
+		else
+		{
+			CrownLib.initRenderer();
+			CrownLib.unpauseDevice();
+		}
 
-} // namespace crown
+		while (CrownLib.isDeviceRunning() && !CrownLib.isDevicePaused())
+		{
+			CrownLib.frame();
+		}
+	}
+}

+ 2 - 2
engine/os/android/CrownSensor.java → engine/os/android/java/CrownSensor.java

@@ -96,7 +96,7 @@ public class CrownSensor
 
                     norm();
 
-                    CrownLib.pushFloatEvent(CrownEnum.OSET_ACCELEROMETER, mGravity[0], mGravity[1], mGravity[2], 0.0f);
+                    CrownLib.pushAccelerometerEvent(CrownEnum.OSET_ACCELEROMETER, mGravity[0], mGravity[1], mGravity[2]);
                 }
             };           
         }
@@ -115,7 +115,7 @@ public class CrownSensor
                     mGeoMagn[1] = (mGeoMagn[1] + event.values[1]) * 0.5f;
                     mGeoMagn[2] = (mGeoMagn[2] + event.values[2]) * 0.5f; 
 
-                    // CrownLib.pushFloatEvent(CrownEnum.OSET_ACCELEROMETER, mGeoMagn[0], mGeoMagn[1], mGeoMagn[2], 0.0f);
+                    // CrownLib.pushAccelerometerEvent(CrownEnum.OSET_ACCELEROMETER, mGeoMagn[0], mGeoMagn[1], mGeoMagn[2], 0.0f);
                 }                
             };
         }

+ 61 - 17
engine/os/android/CrownSurfaceView.java → engine/os/android/java/CrownSurfaceView.java

@@ -30,47 +30,91 @@ import android.content.Context;
 import android.view.Surface;
 import android.view.SurfaceView;
 import android.view.SurfaceHolder;
+import android.graphics.PixelFormat;
+import android.util.Log;
 
 public class CrownSurfaceView extends SurfaceView implements SurfaceHolder.Callback
 {
-	private MainThread mMainThread;
+	private final String TAG = "crown";
 
-	//-----------------------------------------------------------------------------
+	private CrownMainThread mThread;
+
+	private boolean mSurfaceCreated;
+
+//-----------------------------------------------------------------------------
 	public CrownSurfaceView(Context context)
 	{
 		super(context);
 
-		this.getHolder().addCallback(this);
-
-		mMainThread = new MainThread(getHolder(), this);
+		getHolder().addCallback(this);
 
 		setFocusable(true);
+
+		mSurfaceCreated = false;
 	}
 
-	//-----------------------------------------------------------------------------
-	@Override
-	public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) 
+//-----------------------------------------------------------------------------
+	public boolean isSurfaceCreated()
 	{
+		return mSurfaceCreated;
+	}
+
+//-----------------------------------------------------------------------------
+	public void createThread(SurfaceHolder holder)
+	{
+		mThread = new CrownMainThread(holder);
+		mThread.start();
+	}
+
+//-----------------------------------------------------------------------------
+	public void destroyThread()
+	{
+        try
+        {
+        	CrownLib.pauseDevice();
+            mThread.join();
+        }
+        catch (InterruptedException e)
+        {
+            Log.e("crown", "terminateThread corrupts");
+        }     
 	}
 
 	//-----------------------------------------------------------------------------
 	@Override
 	public void surfaceCreated(SurfaceHolder holder) 
 	{
-		mMainThread.start();
+		Log.d(TAG, "Crown Surface created");
+
+		if (!mSurfaceCreated)
+		{
+			mSurfaceCreated = true;
+
+			createThread(holder);
+		}
 	}
 
 	//-----------------------------------------------------------------------------
 	@Override
 	public void surfaceDestroyed(SurfaceHolder holder) 
 	{
-		try
-		{
-			mMainThread.join();
-		}
-		catch (InterruptedException e)
-		{
-			e.printStackTrace();
-		}
+		mSurfaceCreated = false;
+
+		destroyThread();
+
+		CrownLib.pauseDevice();
+
+		CrownLib.destroyWindow();
+
+		CrownLib.shutdownRenderer();
+
+		Log.d(TAG, "Crown Surface destroyed");
+	}
+
+	//-----------------------------------------------------------------------------
+	@Override
+	public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) 
+	{
+		Log.d(TAG, "Crown Surface changed");
 	}
 }

+ 4 - 5
engine/os/android/CrownTouch.java → engine/os/android/java/CrownTouch.java

@@ -35,10 +35,9 @@ import android.view.MotionEvent;
 * CrownTouch manages touch and gesture events passing them to Crown Engine
 */
 
-//TODO: gestures doesn't work...fix them
 public class CrownTouch
 {
-	private boolean 				isListening;
+	private boolean isListening;
 
 //-----------------------------------------------------------------------------------
 	public CrownTouch(Context context)
@@ -63,7 +62,7 @@ public class CrownTouch
 			case MotionEvent.ACTION_DOWN:
 			case MotionEvent.ACTION_POINTER_DOWN:
 			{
-				CrownLib.pushIntEvent(CrownEnum.OSET_TOUCH_DOWN, pointerId, (int)x, (int)y, 0);
+				CrownLib.pushTouchEvent(CrownEnum.OSET_TOUCH_DOWN, pointerId, (int)x, (int)y);
 				break;			
 			}
 
@@ -72,7 +71,7 @@ public class CrownTouch
 			case MotionEvent.ACTION_OUTSIDE:
 			case MotionEvent.ACTION_CANCEL:
 			{
-				CrownLib.pushIntEvent(CrownEnum.OSET_TOUCH_UP, pointerId, (int)x, (int)y, 0);
+				CrownLib.pushTouchEvent(CrownEnum.OSET_TOUCH_UP, pointerId, (int)x, (int)y);
 				break;			
 			}
 			
@@ -80,7 +79,7 @@ public class CrownTouch
 			{
 				for (int index = 0; index < pointerCount; index++)
 				{
-					CrownLib.pushIntEvent(CrownEnum.OSET_TOUCH_MOVE, event.getPointerId(index), (int)event.getX(index), (int)event.getY(index), 0);
+					CrownLib.pushTouchEvent(CrownEnum.OSET_TOUCH_MOVE, event.getPointerId(index), (int)event.getX(index), (int)event.getY(index));
 				}
 
 				break;

+ 19 - 18
engine/os/linux/OsWindow.cpp

@@ -29,6 +29,7 @@ OTHER DEALINGS IN THE SOFTWARE.
 #include "OS.h"
 #include "GLContext.h"
 #include "StringUtils.h"
+#include "OsEvents.h"
 
 namespace crown
 {
@@ -271,8 +272,8 @@ void OsWindow::frame()
 {
 	XEvent event;
 
-	OsEventParameter data_button[4] = {0, 0, 0, 0};
-	OsEventParameter data_key[4] = {0, 0, 0, 0};
+	OsMouseEvent mouse_event;
+	OsKeyboardEvent keyboard_event;
 
 	while (XPending(m_x11_display))
 	{
@@ -293,38 +294,38 @@ void OsWindow::frame()
 			{
 				OsEventType oset_type = event.type == ButtonPress ? OSET_BUTTON_PRESS : OSET_BUTTON_RELEASE;
 
-				data_button[0].int_value = event.xbutton.x;
-				data_button[1].int_value = event.xbutton.y;
+				mouse_event.x = event.xbutton.x;
+				mouse_event.y = event.xbutton.y;
 
 				switch (event.xbutton.button)
 				{
 					case Button1:
 					{
-						data_button[2].int_value = 0;
-						push_event(oset_type, data_button[0], data_button[1], data_button[2], data_button[3]);
+						mouse_event.button = 0;
+						os_event_buffer()->push_event(oset_type, &mouse_event, sizeof(OsMouseEvent));
 						break;
 					}
 					case Button2:
 					{
-						data_button[2].int_value = 1;
-						push_event(oset_type, data_button[0], data_button[1], data_button[2], data_button[3]);
+						mouse_event.button = 1;
+						os_event_buffer()->push_event(oset_type, &mouse_event, sizeof(OsMouseEvent));
 						break;
 					}
 					case Button3:
 					{
-						data_button[2].int_value = 2;
-						push_event(oset_type, data_button[0], data_button[1], data_button[2], data_button[3]);
+						mouse_event.button = 2;
+						os_event_buffer()->push_event(oset_type, &mouse_event, sizeof(OsMouseEvent));
 						break;
 					}
 				}
 
 				break;
 			}
-			case MotionNotify:
-			{
-				push_event(OSET_MOTION_NOTIFY, data_button[0], data_button[1], data_button[2], data_button[3]);
-				break;
-			}
+			// case MotionNotify:
+			// {
+			// 	push_event(OSET_MOTION_NOTIFY, data_button[0], data_button[1], data_button[2], data_button[3]);
+			// 	break;
+			// }
 			case KeyPress:
 			case KeyRelease:
 			{
@@ -353,10 +354,10 @@ void OsWindow::frame()
 
 				OsEventType oset_type = event.type == KeyPress ? OSET_KEY_PRESS : OSET_KEY_RELEASE;
 
-				data_key[0].int_value = ((int32_t)kc);
-				data_key[1].int_value = modifier_mask;
+				keyboard_event.key = ((int32_t)kc);
+				keyboard_event.modifier = modifier_mask;
 
-				push_event(oset_type, data_key[0], data_key[1], data_key[2], data_key[3]);
+				os_event_buffer()->push_event(oset_type, &keyboard_event, sizeof(OsKeyboardEvent));
 
 //				// Text input part
 //				if (event.type == KeyPress && len > 0)

+ 35 - 4
engine/os/linux/main.cpp

@@ -26,18 +26,29 @@ OTHER DEALINGS IN THE SOFTWARE.
 
 #include "Crown.h"
 
-int main(int argc, char** argv)
+namespace crown
+{
+
+struct MainArgs
+{
+	int argc;
+	char** argv;
+};
+
+static Thread thread("main-thread");
+
+int32_t main_thread(void* data)
 {
 	crown::os::init_os();
 
 	crown::Device* engine = crown::device();
 
-	if (!engine->init(argc, argv))
+	MainArgs* args = (MainArgs*)data;
+	if (!engine->init(args->argc, args->argv))
 	{
-		exit(-1);
+		return -1;
 	}
 
-	// Main loop
 	while (engine->is_running())
 	{
 		engine->frame();
@@ -45,6 +56,26 @@ int main(int argc, char** argv)
 
 	engine->shutdown();
 
+	thread.stop();
+
 	return 0;
 }
 
+int32_t ce_main(void* args)
+{
+	thread.start(main_thread, args);
+
+	while (thread.is_running());
+	
+	return 0;
+}
+
+}
+
+int32_t main(int argc, char** argv)
+{
+	crown::MainArgs args;
+	args.argc = argc;
+	args.argv = argv;
+	return crown::ce_main(&args);
+}

+ 35 - 0
engine/os/posix/Cond.h

@@ -27,6 +27,7 @@ OTHER DEALINGS IN THE SOFTWARE.
 #pragma once
 
 #include <pthread.h>
+#include <cstring>
 
 #include "Types.h"
 #include "Mutex.h"
@@ -56,4 +57,38 @@ private:
 	Cond&			operator=(const Cond&);
 };
 
+//-----------------------------------------------------------------------------
+inline Cond::Cond()
+{
+	memset(&m_cond, 0, sizeof(pthread_cond_t));
+
+	int32_t result = pthread_cond_init(&m_cond, NULL);
+
+	CE_ASSERT(result == 0, "Failed to init cond. errno: %d", result);
+}
+
+//-----------------------------------------------------------------------------
+inline Cond::~Cond()
+{
+	int32_t result = pthread_cond_destroy(&m_cond);
+
+	CE_ASSERT(result == 0, "Failed to destroy cond. errno: %d", result);
+}
+
+//-----------------------------------------------------------------------------
+inline void Cond::signal()
+{
+	int32_t result = pthread_cond_signal(&m_cond);
+
+	CE_ASSERT(result == 0, "Failed to signal cond. errno: %d", result);
+}
+
+//-----------------------------------------------------------------------------
+inline void Cond::wait(Mutex& mutex)
+{
+	int32_t result = pthread_cond_wait(&m_cond, &(mutex.m_mutex));
+
+	CE_ASSERT(result == 0, "Failed to wait cond. errno: %d", result);
+}
+
 } // namespace crown

+ 36 - 0
engine/os/posix/Mutex.h

@@ -27,9 +27,11 @@ OTHER DEALINGS IN THE SOFTWARE.
 #pragma once
 
 #include <pthread.h>
+#include <cstring>
 
 #include "Types.h"
 #include "OS.h"
+#include "Assert.h"
 
 namespace crown
 {
@@ -57,4 +59,38 @@ private:
 	friend class		Cond;
 };
 
+//-----------------------------------------------------------------------------
+inline Mutex::Mutex()
+{
+	memset(&m_mutex, 0, sizeof(pthread_mutex_t));
+
+	int32_t result = pthread_mutex_init(&m_mutex, NULL);
+
+	CE_ASSERT(result == 0, "Failed to init mutex. errno: %d", result);
+}
+
+//-----------------------------------------------------------------------------
+inline Mutex::~Mutex()
+{
+	int32_t result = pthread_mutex_destroy(&m_mutex);
+
+	CE_ASSERT(result == 0, "Failed to destroy mutex. errno: %d", result);
+}
+
+//-----------------------------------------------------------------------------
+inline void Mutex::lock()
+{
+	int32_t result = pthread_mutex_lock(&m_mutex);
+
+	CE_ASSERT(result == 0, "Failed to acquire lock. errno: %d", result);
+}
+
+//-----------------------------------------------------------------------------
+inline void Mutex::unlock()
+{
+	int32_t result = pthread_mutex_unlock(&m_mutex);
+
+	CE_ASSERT(result == 0, "Failed to release lock. errno: %d", result);
+}
+
 } // namespace crown

+ 56 - 12
engine/os/posix/Mutex.cpp → engine/os/posix/Semaphore.h

@@ -24,37 +24,81 @@ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 OTHER DEALINGS IN THE SOFTWARE.
 */
 
-#include <string.h>
+#pragma once
 
+#include <errno.h>
+#include <semaphore.h>
+
+#include "Assert.h"
 #include "Mutex.h"
+#include "Cond.h"
+#include "Log.h"
 
 namespace crown
 {
 
-//-----------------------------------------------------------------------------
-Mutex::Mutex()
+class Semaphore
 {
-	memset(&m_mutex, 0, sizeof(pthread_mutex_t));
+public:
+
+			Semaphore();
+			~Semaphore();
+
+	void	post(uint32_t count = 1);
+	void	wait();
+
+private:
+
+	Mutex 	m_mutex;
+	Cond 	m_cond;
+
+	int32_t m_count;
+
+private:
+
+	Semaphore(const Semaphore& s); // no copy constructor
+	Semaphore& operator=(const Semaphore& s); // no assignment operator
+};
 
-	pthread_mutex_init(&m_mutex, NULL);
+//-----------------------------------------------------------------------------
+inline Semaphore::Semaphore() : m_count(0)
+{
 }
 
 //-----------------------------------------------------------------------------
-Mutex::~Mutex()
+inline Semaphore::~Semaphore()
 {
-	pthread_mutex_destroy(&m_mutex);
 }
 
 //-----------------------------------------------------------------------------
-void Mutex::lock()
+inline void Semaphore::post(uint32_t count)
 {
-	pthread_mutex_lock(&m_mutex);
+	m_mutex.lock();
+
+	for (uint32_t i = 0; i < count; i++)
+	{
+		m_cond.signal();
+	}
+
+	m_count += count;
+
+	m_mutex.unlock();	
 }
 
 //-----------------------------------------------------------------------------
-void Mutex::unlock()
+inline void Semaphore::wait()
 {
-	pthread_mutex_unlock(&m_mutex);
+	m_mutex.lock();
+
+	while (m_count <= 0)
+	{
+		m_cond.wait(m_mutex);
+	}
+
+	m_count--;
+
+	m_mutex.unlock();
 }
 
-} // namespace crown
+
+} // namespace crown

+ 0 - 125
engine/os/posix/Thread.cpp

@@ -1,125 +0,0 @@
-/*
-Copyright (c) 2013 Daniele Bartolini, Michele Rossi
-Copyright (c) 2012 Daniele Bartolini, Simone Boscaratto
-
-Permission is hereby granted, free of charge, to any person
-obtaining a copy of this software and associated documentation
-files (the "Software"), to deal in the Software without
-restriction, including without limitation the rights to use,
-copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the
-Software is furnished to do so, subject to the following
-conditions:
-
-The above copyright notice and this permission notice shall be
-included in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
-OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
-HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-OTHER DEALINGS IN THE SOFTWARE.
-*/
-
-#include <stdlib.h>
-#include <string.h>
-
-#include "Thread.h"
-#include "Assert.h"
-
-namespace crown
-{
-
-//-----------------------------------------------------------------------------
-Thread::Thread(const char* name) :
-	m_name(name),
-	m_is_running(false),
-	m_is_terminating(false),
-	m_thread(0)
-{
-	memset(&m_thread, 0, sizeof(pthread_t));
-}
-
-//-----------------------------------------------------------------------------
-Thread::~Thread()
-{
-}
-
-//-----------------------------------------------------------------------------
-const char* Thread::name() const
-{
-	return m_name;
-}
-
-//-----------------------------------------------------------------------------
-void Thread::start()
-{
-	m_is_terminating = false;
-
-	// Make thread joinable
-	pthread_attr_t attr;
-	pthread_attr_init(&attr);
-	pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
-
-	// Create thread
-	int rc = pthread_create(&m_thread, &attr, Thread::background_proc, (void*) this);
-	CE_ASSERT(rc == 0, "Failed to create the thread '%s': errno: %d", m_name, rc);
-
-	// Free attr memory
-	pthread_attr_destroy(&attr);
-
-	m_is_running = true;
-}
-
-//-----------------------------------------------------------------------------
-bool Thread::is_running() const
-{
-	return m_is_running;
-}
-
-//-----------------------------------------------------------------------------
-bool Thread::is_terminating() const
-{
-	return m_is_terminating;
-}
-
-//-----------------------------------------------------------------------------
-void Thread::stop()
-{
-	m_is_terminating = true;
-}
-
-//-----------------------------------------------------------------------------
-int32_t Thread::run()
-{
-	return 0;
-}
-
-//-----------------------------------------------------------------------------
-void* Thread::background_proc(void* thiz)
-{
-	Thread* thread = ((Thread*) thiz);
-
-	thread->run();
-
-	thread->m_is_running = false;
-
-	return NULL;
-}
-
-//-----------------------------------------------------------------------------
-void Thread::join()
-{
-	pthread_join(m_thread, NULL);
-}
-
-//-----------------------------------------------------------------------------
-void Thread::detach()
-{
-	pthread_detach(m_thread);
-}
-
-} // namespace crown

+ 113 - 45
engine/os/posix/Thread.h

@@ -26,74 +26,142 @@ OTHER DEALINGS IN THE SOFTWARE.
 
 #pragma once
 
-#include <pthread.h>
+#include <cstring>
 
+#include "Assert.h"
 #include "Types.h"
+#include "Semaphore.h"
+#include "Log.h"
 
 namespace crown
 {
 
-typedef void* (*ThreadFunction)(void*);
+typedef int32_t (*ThreadFunction)(void*);
 
 class Thread
 {
 public:
 
-	/// Constructs the thread and gives it a @a name.
-	/// @note
-	/// The actual OS thread creation and execution is
-	/// deferred to the first call to Thread::start().
-					Thread(const char* name);
+						Thread(const char* name);
+						~Thread();
 
-	/// Does not stop the thread. The user must call
-	/// Thread::stop() to effectively stop the thread. 
-	virtual			~Thread();
+	void				start(ThreadFunction func, void* data = NULL, size_t stack_size = 0);
+	void				stop();
 
-	/// Returns the name of the thread.
-	const char*		name() const;
+	bool				is_running();
 
-	void			join();
-	void			detach();
+private:
 
-	/// Returns whether the thread is currently running.
-	bool			is_running() const;
+	int32_t				run();
 
-	/// Returns whether the thread is being asked to stop running.
-	/// @note
-	/// The implementer tipically polls this function to
-	/// determine whether to stop the execution or not.
-	bool			is_terminating() const;
+	static void* 		thread_proc(void* arg);
 
-	/// Starts the execution of the thread.
-	/// The function creates the OS thread and starts
-	/// its execution.
-	void			start();
+private:
 
-	/// Stops the execution of the thread if it is running.
-	/// The function releases the OS thread causing its
-	/// termination.
-	void			stop();
+	const char* 		m_name;
 
-	/// Executes in background when the thead is running.
-	/// The thread has to be started with Thread::start()
-	virtual int32_t	run();
+	pthread_t			m_handle;
+	ThreadFunction 	m_function;
+	void*				m_data;
+	Semaphore			m_sem;
+	size_t 				m_stack_size;
 
-private:
+	bool				m_is_running :1;
+};
 
-	static void*	background_proc(void* thiz);
+//-----------------------------------------------------------------------------
+inline Thread::Thread(const char* name) :
+	m_name(name),
+	m_handle(0),
+	m_function(NULL),
+	m_data(NULL),
+	m_stack_size(0),
+	m_is_running(false)
+{
+	memset(&m_handle, 0, sizeof(pthread_t));
+}
 
-private:
+//-----------------------------------------------------------------------------
+inline Thread::~Thread()
+{
+}
 
-	const char*		m_name;
-	bool			m_is_running;
-	bool			m_is_terminating;
-	pthread_t		m_thread;
+//-----------------------------------------------------------------------------
+inline void Thread::start(ThreadFunction func, void* data, size_t stack_size)
+{
+	CE_ASSERT(!m_is_running, "Thread is already running");
+	CE_ASSERT(func != NULL, "Function must be != NULL");
 
-private:
+	m_function = func;
+	m_data = data;
+	m_stack_size = stack_size;
+
+	pthread_attr_t attr;
+	int32_t result = pthread_attr_init(&attr);
+	pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
+
+
+	CE_ASSERT(result == 0, "pthread_attr_init failed. errno: %d", result);
+
+	if (m_stack_size != 0)
+	{
+		result = pthread_attr_setstacksize(&attr, m_stack_size);
+		CE_ASSERT(result == 0, "pthread_attr_setstacksize failed. errno: %d", result);
+	}
+
+	result = pthread_create(&m_handle, &attr, thread_proc, this);
+	CE_ASSERT(result == 0, "pthread_create failed. errno: %d", result);
+
+	// Free attr memory
+	result = pthread_attr_destroy(&attr);
+	CE_ASSERT(result == 0, "pthread_attr_destroy failed. errno: %d", result);
+
+	m_is_running = true;
+
+	m_sem.wait();
+}
+
+//-----------------------------------------------------------------------------
+inline void Thread::stop()
+{
+	CE_ASSERT(m_is_running, "Thread is not running");
+	
+	m_is_running = false;
+
+	int32_t result = pthread_join(m_handle, NULL);
+
+	CE_ASSERT(result == 0, "Thread join failed. errno: %d", result);
+
+	m_handle = 0;
+}
+
+//-----------------------------------------------------------------------------
+inline bool Thread::is_running()
+{
+	return m_is_running;
+}
+
+//-----------------------------------------------------------------------------
+inline int32_t Thread::run()
+{
+	m_sem.post();
+	
+	return m_function(m_data);
+}
+
+//-----------------------------------------------------------------------------
+inline void* Thread::thread_proc(void* arg)
+{
+	Thread* thread = (Thread*)arg;
+
+	int32_t result = thread->run();
+
+	CE_ASSERT(result == 0, "Function failed");
+
+	thread->m_is_running = false;
+
+	return NULL;
+}
 
-	// Disable copying
-					Thread(const Thread&);
-	Thread&			operator=(const Thread&);
-};
 
-} // namespace crown
+} // namespace crown

+ 72 - 33
engine/renderers/gl/egl/GLContext.cpp

@@ -26,78 +26,117 @@ OTHER DEALINGS IN THE SOFTWARE.
 
 #include <GLES2/gl2.h>
 
+#include "Config.h"
 #include "Assert.h"
 #include "GLContext.h"
+#include "Log.h"
 
 namespace crown
 {
 
-static ANativeWindow* awindow = NULL;
+extern ANativeWindow* g_android_window;
 
 //-----------------------------------------------------------------------------
-void set_android_window(ANativeWindow* window)
+static const char* egl_error_to_string(EGLint error)
 {
-    CE_ASSERT_NOT_NULL(window);
-
-	awindow = window;
+	switch (error)
+	{
+		case EGL_NOT_INITIALIZED: return "EGL_NOT_INITIALIZED";
+		case EGL_BAD_ACCESS: return "EGL_BAD_ACCESS";
+		case EGL_BAD_ALLOC: return "EGL_BAD_ALLOC";
+		case EGL_BAD_ATTRIBUTE: return "EGL_BAD_ATTRIBUTE";
+		case EGL_BAD_CONTEXT: return "EGL_BAD_CONTEXT";
+		case EGL_BAD_CONFIG: return "EGL_BAD_CONFIG";
+		case EGL_BAD_CURRENT_SURFACE: return "EGL_BAD_CURRENT_SURFACE";
+		case EGL_BAD_DISPLAY: return "EGL_BAD_DISPLAY";
+		case EGL_BAD_SURFACE: return "EGL_BAD_SURFACE";
+		case EGL_BAD_MATCH: return "EGL_BAD_MATCH";
+		case EGL_BAD_PARAMETER: return "EGL_BAD_PARAMETER";
+		case EGL_BAD_NATIVE_PIXMAP: return "EGL_BAD_NATIVE_PIXMAP";
+		case EGL_BAD_NATIVE_WINDOW: return "EGL_BAD_NATIVE_WINDOW";
+		case EGL_CONTEXT_LOST: return "EGL_CONTEXT_LOST";
+		default: return "UNKNOWN_EGL_ERROR";
+	}
 }
 
 //-----------------------------------------------------------------------------
-GLContext::GLContext() :
-	num_configs(0)
+#if defined(CROWN_DEBUG) || defined(CROWN_DEVELOPMENT)
+	#define EGL_CHECK(function)\
+		function;\
+		do { EGLint error; CE_ASSERT((error = eglGetError()) == EGL_SUCCESS,\
+				"EGL error: %s", egl_error_to_string(error)); } while (0)
+#else
+	#define EGL_CHECK(function)\
+		function;
+#endif
+
+//-----------------------------------------------------------------------------
+GLContext::GLContext()
+	: display(EGL_NO_DISPLAY), surface(EGL_NO_SURFACE), context(EGL_NO_CONTEXT), num_configs(0)
 {
 }
 
 //-----------------------------------------------------------------------------
 void GLContext::create_context()
 {
-	EGLint format;
+    const EGLint attrib_list[] = {
+            EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
+            EGL_BLUE_SIZE, 8,
+            EGL_GREEN_SIZE, 8,
+            EGL_RED_SIZE, 8,
+            EGL_NONE
+    };
 
-	// Screen format rgbx8888 with no alpha channel,
-	// maybe it is wrong but is for testing
-	EGLint attrib_list[]= { EGL_RED_SIZE,        8,
-                            EGL_GREEN_SIZE,      8,
-                            EGL_BLUE_SIZE,       8,
-                            EGL_DEPTH_SIZE,      24,
-                            EGL_SURFACE_TYPE,    EGL_WINDOW_BIT,
-                            EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
-                            EGL_NONE};
+	EGLint attributes[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
 
-    EGLint attributes[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
+	display = EGL_CHECK(eglGetDisplay(EGL_DEFAULT_DISPLAY));
+	CE_ASSERT(display != EGL_NO_DISPLAY, "Failed to obtain EGL display connection");
 
-    display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+	EGLint egl_major, egl_minor;
+	EGLBoolean init_success = EGL_CHECK(eglInitialize(display, &egl_major, &egl_minor));
+	CE_ASSERT(init_success == EGL_TRUE, "Failed to initialize EGL");
 
-    eglInitialize(display, NULL, NULL);
+	Log::d("EGL Initialized: major = %d, minor = %d", egl_major, egl_minor);
 
-    eglBindAPI(EGL_OPENGL_ES_API);
+	EGLBoolean bind_success = EGL_CHECK(eglBindAPI(EGL_OPENGL_ES_API));
+	CE_ASSERT(bind_success != EGL_FALSE, "Failed to bind OpenGL|ES API");
 
-    eglChooseConfig(display, attrib_list, &config, 1, &num_configs);
+	EGLBoolean cfg_success = EGL_CHECK(eglChooseConfig(display, attrib_list, &config, 1, &num_configs));
+	CE_ASSERT(cfg_success == EGL_TRUE, "Failed to choose EGL configuration");
 
-	eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &format);
+	EGLint format;
+	EGL_CHECK(eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &format));
 
-	ANativeWindow_setBuffersGeometry(awindow, 0, 0, format);
+	ANativeWindow_setBuffersGeometry(g_android_window, 0, 0, format);
 
-    context = eglCreateContext(display, config, EGL_NO_CONTEXT, attributes);
+	context = EGL_CHECK(eglCreateContext(display, config, EGL_NO_CONTEXT, attributes));
+	CE_ASSERT(context != EGL_NO_CONTEXT, "Oops, failed to create EGL context");
 
-	surface = eglCreateWindowSurface(display, config, (EGLNativeWindowType)awindow, NULL);
+	surface = EGL_CHECK(eglCreateWindowSurface(display, config, (EGLNativeWindowType)g_android_window, NULL));
+	CE_ASSERT(surface != EGL_NO_SURFACE, "Oops, failed to create EGL surface");
 
-    eglMakeCurrent(display, surface, surface, context);
+	EGL_CHECK(eglMakeCurrent(display, surface, surface, context));
+
+	Log::d("EGL context created");
 }
 
 //-----------------------------------------------------------------------------
 void GLContext::destroy_context()
 {
- 	eglDestroyContext(display, context);
- 	eglDestroySurface(display, surface);
- 	eglTerminate(display);
-
+	EGL_CHECK(eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT));
+	EGL_CHECK(eglDestroyContext(display, context));
+	EGL_CHECK(eglDestroySurface(display, surface));
+	EGL_CHECK(eglTerminate(display));
     display = EGL_NO_DISPLAY;
+
+	Log::i("EGL context destroyed");
 }
 
 //-----------------------------------------------------------------------------
 void GLContext::swap_buffers()
 {
-   	eglSwapBuffers(display, surface);
+	EGL_CHECK(eglMakeCurrent(display, surface, surface, context));
+	EGL_CHECK(eglSwapBuffers(display, surface));
 }
 
-}
+}

+ 4 - 7
engine/renderers/gl/egl/GLContext.h

@@ -27,13 +27,10 @@ OTHER DEALINGS IN THE SOFTWARE.
 #pragma once
 
 #include <EGL/egl.h>
-#include <android/native_window.h>
 
 namespace crown
 {
 
-void set_android_window(ANativeWindow* window);
-
 class GLContext
 {
 public:
@@ -52,11 +49,11 @@ public:
 private:
 
 	EGLDisplay 		display;
-    EGLSurface 		surface;
-    EGLConfig 		config;
-    EGLContext 		context;
+	EGLSurface 		surface;
+	EGLConfig 		config;
+	EGLContext 		context;
 
-    int32_t			num_configs;
+	int32_t			num_configs;
 };
 
 } // namespace crown

+ 2 - 2
engine/resource/ResourceLoader.cpp

@@ -33,7 +33,7 @@ namespace crown
 
 //-----------------------------------------------------------------------------
 ResourceLoader::ResourceLoader(Bundle& bundle, Allocator& resource_heap) :
-	Thread("resource-loader"),
+	m_thread("resource-loader"),
 	m_bundle(bundle),
 	m_resource_heap(resource_heap),
 	m_num_requests(0),
@@ -94,7 +94,7 @@ void* ResourceLoader::load_resource_data(LoadResourceId id) const
 //-----------------------------------------------------------------------------
 int32_t ResourceLoader::run()
 {
-	while (!is_terminating())
+	while (m_thread.is_running())
 	{
 		m_requests_mutex.lock();
 		while (m_requests.empty())

+ 20 - 1
engine/resource/ResourceLoader.h

@@ -66,7 +66,7 @@ struct LoadResourceData
 };
 
 /// Loads resources in a background thread.
-class ResourceLoader : public Thread
+class ResourceLoader
 {
 public:
 
@@ -86,8 +86,27 @@ public:
 	// Loads resources in the loading queue.
 	int32_t					run();
 
+	void start()
+	{
+		m_thread.start(background_run, this);
+	}
+
+	void stop()
+	{
+		m_thread.stop();
+	}
+
+private:
+
+	static int32_t background_run(void* thiz)
+	{
+		return ((ResourceLoader*)thiz)->run();
+	}
+
 private:
 
+	Thread					m_thread;
+
 	// Whether to look for resources
 	Bundle&					m_bundle;
 

+ 6 - 1
engine/tests/CMakeLists.txt

@@ -11,6 +11,8 @@ add_executable(strings strings.cpp)
 add_executable(paths paths.cpp)
 add_executable(dynamic-strings dynamic-strings.cpp)
 add_executable(json json.cpp)
+add_executable(events events.cpp)
+add_executable(threads threads.cpp)
 
 target_link_libraries(allocators crown)
 target_link_libraries(containers crown)
@@ -19,6 +21,8 @@ target_link_libraries(strings crown)
 target_link_libraries(paths crown)
 target_link_libraries(dynamic-strings crown)
 target_link_libraries(json crown)
+target_link_libraries(events crown)
+target_link_libraries(threads crown)
 
 add_test(allocators-test ${EXECUTABLE_OUTPUT_PATH}/allocators)
 add_test(containers-test ${EXECUTABLE_OUTPUT_PATH}/containers)
@@ -27,4 +31,5 @@ add_test(strings-test ${EXECUTABLE_OUTPUT_PATH}/strings)
 add_test(paths-test ${EXECUTABLE_OUTPUT_PATH}/paths)
 add_test(dynamic-string-test ${EXECUTABLE_OUTPUT_PATH}/dynamic-strings)
 add_test(json-test ${EXECUTABLE_OUTPUT_PATH}/json)
-
+add_test(events-test ${EXECUTABLE_OUTPUT_PATH}/events)
+add_test(threads-test ${EXECUTABLE_OUTPUT_PATH}/threads)

+ 90 - 0
engine/tests/events.cpp

@@ -0,0 +1,90 @@
+#include "Crown.h"
+#include "EventBuffer.h"
+
+using namespace crown;
+
+//-----------------------------------------------------------------------------
+struct TestEvent
+{
+	uint32_t a;
+	uint32_t b;
+	uint32_t c;
+};
+
+//-----------------------------------------------------------------------------
+void fill_events(EventBuffer& event_buffer, uint32_t num)
+{
+	TestEvent event;
+	event.a = 1;
+	event.b = 2;
+	event.c = 3;
+
+	for (uint32_t i = 0; i < num; i++)
+	{
+		event_buffer.push_event(0, &event, sizeof(TestEvent));
+	}
+
+	uint32_t size = num * (sizeof(TestEvent) + sizeof(uint32_t) + sizeof(size_t));
+
+	CE_ASSERT(event_buffer.size() == size, "Something ha gone wrong, size is %d, should be %d", event_buffer.size(), size);
+}
+
+void get_events(EventBuffer& event_buffer, uint32_t num)
+{
+	TestEvent* result;
+	uint32_t type = 0;
+	size_t size = 0;
+
+	uint32_t count = 0;
+
+	for (uint32_t i = 0; i < num; i++)
+	{
+		result = (TestEvent*)event_buffer.get_next_event(type, size);
+
+		if (result)
+		{
+			count++;
+		}
+
+		Log::i("count: %d", count);
+	}
+
+	CE_ASSERT(count == num, "Something ha gone wrong, count: %d, num: %d", count, num);
+}
+
+void get_event_until_end(EventBuffer& event_buffer)
+{
+	TestEvent* result;
+	uint32_t type = 0;
+	size_t size = 0;
+
+	int32_t count = 0;
+
+	while ((result = (TestEvent*)event_buffer.get_next_event(type, size)) != NULL)
+	{
+		count++;
+	}
+
+	Log::i("count: %d", count);
+}
+
+//-----------------------------------------------------------------------------
+int main()
+{
+	EventBuffer event_buffer;
+
+	fill_events(event_buffer, 10);
+	get_events(event_buffer, 10);
+
+	event_buffer.clear();
+
+	fill_events(event_buffer, 5);
+	get_events(event_buffer, 5);
+
+	event_buffer.clear();
+
+	fill_events(event_buffer, 30);
+	get_event_until_end(event_buffer);
+
+	return 0;
+}

+ 31 - 0
engine/tests/threads.cpp

@@ -0,0 +1,31 @@
+#include "Thread.h"
+#include "Log.h"
+
+#include <unistd.h>
+
+using namespace crown;
+
+int32_t first_function(void* ft)
+{
+	Thread* thread = (Thread*)ft;
+
+	while(thread->is_running())
+	{
+		Log::i("I'm in the first thread");
+	}
+
+	return 0;
+}
+	
+int main()
+{
+	Thread ft("first-thread");
+
+	ft.start(first_function, &ft);
+
+	sleep(2);
+
+	ft.stop();
+
+	return 0;
+}

+ 1 - 1
utils/crown-android.rb

@@ -32,7 +32,7 @@ $activity			= "CrownActivity"
 $package			= "crown.android"
 
 $engine_src 		= "../engine/."
-$android_src		= "../engine/os/android/*.java"
+$android_src		= "../engine/os/android/java/."
 $config_src			= "../engine/os/android/Config.h"
 $manifest			= "../engine/os/android/AndroidManifest.xml"