Преглед на файлове

Merge branch 'master' into rpc

Conflicts:
	engine/tests/CMakeLists.txt
Daniele Bartolini преди 12 години
родител
ревизия
f02c1ce099
променени са 100 файла, в които са добавени 5445 реда и са изтрити 9399 реда
  1. 1 1
      CMakeLists.txt
  2. 6 11
      engine/Android.mk
  3. 22 17
      engine/CMakeLists.txt
  4. 12 0
      engine/Config.h.in
  5. 1 4
      engine/Crown.h
  6. 157 27
      engine/Device.cpp
  7. 39 6
      engine/Device.h
  8. 94 0
      engine/EventBuffer.cpp
  9. 41 3
      engine/EventBuffer.h
  10. 2 2
      engine/FPSSystem.cpp
  11. 28 13
      engine/compilers/BundleCompiler.cpp
  12. 4 0
      engine/compilers/BundleCompiler.h
  13. 0 633
      engine/compilers/dae/DAECompiler.cpp
  14. 0 199
      engine/compilers/dae/DAECompiler.h
  15. 0 2099
      engine/compilers/dae/tinyxml2.cpp
  16. 0 1968
      engine/compilers/dae/tinyxml2.h
  17. 17 2
      engine/compilers/lua/LuaCompiler.cpp
  18. 199 0
      engine/compilers/mesh/MeshCompiler.cpp
  19. 38 4
      engine/compilers/mesh/MeshCompiler.h
  20. 139 0
      engine/compilers/package/PackageCompiler.cpp
  21. 18 10
      engine/compilers/package/PackageCompiler.h
  22. 2 2
      engine/compilers/texture/TextureCompiler.cpp
  23. 26 42
      engine/core/containers/IdTable.h
  24. 222 18
      engine/core/json/JSONParser.cpp
  25. 40 7
      engine/core/json/JSONParser.h
  26. 0 38
      engine/core/mem/Allocator.cpp
  27. 15 5
      engine/core/mem/LinearAllocator.cpp
  28. 2 0
      engine/core/mem/LinearAllocator.h
  29. 43 16
      engine/core/mem/Memory.cpp
  30. 10 0
      engine/core/mem/Memory.h
  31. 1 0
      engine/core/strings/StringStream.h
  32. 38 31
      engine/input/InputManager.cpp
  33. 29 4
      engine/lua/LuaDevice.cpp
  34. 57 135
      engine/lua/LuaEnvironment.cpp
  35. 13 19
      engine/lua/LuaEnvironment.h
  36. 39 65
      engine/lua/LuaResourcePackage.cpp
  37. 1 1
      engine/lua/LuaStack.h
  38. 32 5
      engine/lua/LuaWindow.cpp
  39. 5 39
      engine/os/OS.cpp
  40. 8 38
      engine/os/OS.h
  41. 44 24
      engine/os/OsEvents.h
  42. 58 6
      engine/os/android/AndroidDevice.cpp
  43. 38 18
      engine/os/android/AndroidOS.cpp
  44. 2 2
      engine/os/android/ApkFilesystem.cpp
  45. 14 2
      engine/os/android/Config.h
  46. 0 58
      engine/os/android/MainThread.java
  47. 36 23
      engine/os/android/OsWindow.cpp
  48. 12 4
      engine/os/android/OsWindow.h
  49. 19 35
      engine/os/android/java/CrownActivity.java
  50. 0 0
      engine/os/android/java/CrownEnum.java
  51. 24 10
      engine/os/android/java/CrownLib.java
  52. 28 27
      engine/os/android/java/CrownMainThread.java
  53. 2 2
      engine/os/android/java/CrownSensor.java
  54. 61 17
      engine/os/android/java/CrownSurfaceView.java
  55. 4 5
      engine/os/android/java/CrownTouch.java
  56. 27 0
      engine/os/linux/LinuxOS.cpp
  57. 58 22
      engine/os/linux/OsWindow.cpp
  58. 8 2
      engine/os/linux/OsWindow.h
  59. 3 7
      engine/os/linux/main.cpp
  60. 320 0
      engine/os/linux/main2.cpp
  61. 0 60
      engine/os/posix/Cond.cpp
  62. 35 0
      engine/os/posix/Cond.h
  63. 36 0
      engine/os/posix/Mutex.h
  64. 56 12
      engine/os/posix/Semaphore.h
  65. 0 125
      engine/os/posix/Thread.cpp
  66. 106 45
      engine/os/posix/Thread.h
  67. 2 8
      engine/os/win/OsWindow.cpp
  68. 1 2
      engine/os/win/OsWindow.h
  69. 51 5
      engine/os/win/Thread.cpp
  70. 19 2
      engine/os/win/Thread.h
  71. 90 9
      engine/os/win/WinOS.cpp
  72. 305 0
      engine/os/win/inttypes.h
  73. 98 0
      engine/renderers/CommandBuffer.h
  74. 114 0
      engine/renderers/ConstantBuffer.h
  75. 1 1
      engine/renderers/DebugRenderer.cpp
  76. 0 105
      engine/renderers/Material.h
  77. 0 117
      engine/renderers/PixelFormat.cpp
  78. 24 70
      engine/renderers/PixelFormat.h
  79. 0 33
      engine/renderers/PixelShader.h
  80. 327 0
      engine/renderers/RenderContext.h
  81. 645 168
      engine/renderers/Renderer.h
  82. 161 0
      engine/renderers/RendererTypes.h
  83. 79 10
      engine/renderers/VertexFormat.h
  84. 0 33
      engine/renderers/VertexShader.h
  85. 415 840
      engine/renderers/gl/GLRenderer.cpp
  86. 493 199
      engine/renderers/gl/GLRenderer.h
  87. 0 139
      engine/renderers/gl/GLUtils.h
  88. 142 0
      engine/renderers/gl/egl/GLContext.cpp
  89. 9 7
      engine/renderers/gl/egl/GLContext.h
  90. 3 1
      engine/renderers/gl/glx/GLContext.cpp
  91. 6 1
      engine/renderers/gl/glx/GLContext.h
  92. 0 972
      engine/renderers/gles/GLESRenderer.cpp
  93. 0 276
      engine/renderers/gles/GLESRenderer.h
  94. 0 105
      engine/renderers/gles/GLESUtils.cpp
  95. 0 143
      engine/renderers/gles/GLESUtils.h
  96. 0 101
      engine/renderers/gles/egl/GLContext.cpp
  97. 1 0
      engine/resource/FileBundle.cpp
  98. 0 1
      engine/resource/LuaResource.h
  99. 0 56
      engine/resource/MaterialResource.h
  100. 67 25
      engine/resource/MeshResource.h

+ 1 - 1
CMakeLists.txt

@@ -4,7 +4,7 @@ project(crown)
 
 set (CROWN_VERSION_MAJOR 0)
 set (CROWN_VERSION_MINOR 1)
-set (CROWN_VERSION_MICRO 11)
+set (CROWN_VERSION_MICRO 12)
 
 option (CROWN_BUILD_SAMPLES "Whether to build the samples" ON)
 option (CROWN_BUILD_TOOLS "Whether to build the tools" ON)

+ 6 - 11
engine/Android.mk

@@ -39,7 +39,6 @@ LOCAL_SRC_FILES :=\
 	core/math/Vec3.cpp\
 	core/math/Vec4.cpp\
 \
-	core/mem/Allocator.cpp\
 	core/mem/HeapAllocator.cpp\
 	core/mem/LinearAllocator.cpp\
 	core/mem/ProxyAllocator.cpp\
@@ -69,18 +68,12 @@ 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\
 \
-	renderers/gles/GLESRenderer.cpp\
-	renderers/gles/GLESUtils.cpp\
-	renderers/gles/egl/GLContext.cpp\
+	renderers/gl/GLRenderer.cpp\
+	renderers/gl/egl/GLContext.cpp\
 	renderers/DebugRenderer.cpp\
-	renderers/PixelFormat.cpp\
-	renderers/VertexFormat.cpp\
 \
 	resource/FileBundle.cpp\
 	resource/ResourceLoader.cpp\
@@ -103,11 +96,13 @@ LOCAL_SRC_FILES :=\
 	lua/LuaIntSetting.cpp\
 	lua/LuaFloatSetting.cpp\
 	lua/LuaStringSetting.cpp\
+	lua/LuaResourcePackage.cpp\
 \
 	Camera.cpp\
 	Device.cpp\
 	FPSSystem.cpp\
 	ConsoleServer.cpp\
+	EventBuffer.cpp\
 \
 
 LOCAL_C_INCLUDES	:=\
@@ -131,8 +126,8 @@ LOCAL_C_INCLUDES	:=\
 	$(LOCAL_PATH)/os/android\
 	$(LOCAL_PATH)/os/posix\
 	$(LOCAL_PATH)/renderers\
-	$(LOCAL_PATH)/renderers/gles\
-	$(LOCAL_PATH)/renderers/gles/egl\
+	$(LOCAL_PATH)/renderers/gl\
+	$(LOCAL_PATH)/renderers/gl/egl\
 	$(LOCAL_PATH)/luajit/include/luajit-2.0\
 
 LOCAL_CPPFLAGS	:= -g -fexceptions -std=c++03 -ansi -pedantic -Wall -Wextra -Wno-long-long -Wno-variadic-macros

+ 22 - 17
engine/CMakeLists.txt

@@ -61,11 +61,13 @@ set (CROWN_INCLUDES
 	${CMAKE_SOURCE_DIR}/engine/compilers/lua
 	${CMAKE_SOURCE_DIR}/engine/compilers/texture
 	${CMAKE_SOURCE_DIR}/engine/compilers/mesh
+	${CMAKE_SOURCE_DIR}/engine/compilers/package
 )
 
 set (SRC
 	Camera.cpp
 	Device.cpp
+	EventBuffer.cpp
 	ConsoleServer.cpp
 	FPSSystem.cpp
 )
@@ -75,6 +77,7 @@ set (HEADERS
 	Config.h
 	Crown.h
 	Device.h
+	EventBuffer.h
 	ConsoleServer.h
 	FPSSystem.h
 )
@@ -189,7 +192,6 @@ set (STRINGS_HEADERS
 
 set (MEM_SRC
 	core/mem/Memory.cpp
-	core/mem/Allocator.cpp
 	core/mem/HeapAllocator.cpp
 	core/mem/LinearAllocator.cpp
 	core/mem/StackAllocator.cpp
@@ -255,16 +257,11 @@ set (NETWORK_HEADERS
 
 set (RENDERERS_SRC
 	renderers/DebugRenderer.cpp
-	renderers/PixelFormat.cpp
-	renderers/VertexFormat.cpp
 )
 
 set (RENDERERS_HEADERS
 	renderers/Renderer.h
-	renderers/IndexBuffer.h
-	renderers/VertexBuffer.h
-	renderers/Material.h
-	renderers/Texture.h
+	renderers/RenderContext.h
 	renderers/DebugRenderer.h
 	renderers/PixelFormat.h
 	renderers/VertexFormat.h
@@ -285,7 +282,6 @@ else ()
 endif (CROWN_DEBUG OR CROWN_DEVELOPMENT)
 
 set (RESOURCE_HEADERS
-
 	resource/Resource.h
 	resource/ResourceFormat.h
 	resource/ResourceLoader.h
@@ -298,6 +294,8 @@ set (RESOURCE_HEADERS
 	resource/FontResource.h
 	resource/SoundResource.h
 	resource/MaterialResource.h
+	resource/PackageResource.h
+	resource/ResourcePackage.h
 )
 
 set (RPC_SRC
@@ -325,6 +323,7 @@ set (OS_SRC
 set (OS_HEADERS
 	os/OS.h
 	os/NetAddress.h
+	os/OsEvents.h
 )
 
 set (LUA_SRC
@@ -343,6 +342,7 @@ set (LUA_SRC
 	lua/LuaAccelerometer.cpp
 	lua/LuaDevice.cpp
 	lua/LuaWindow.cpp
+	lua/LuaResourcePackage.cpp
 )
 
 set (LUA_HEADERS
@@ -353,15 +353,19 @@ set (LUA_HEADERS
 set (COMPILER_SRC
 	compilers/Compiler.cpp
 	compilers/BundleCompiler.cpp
+	compilers/mesh/MeshCompiler.cpp
 	compilers/lua/LuaCompiler.cpp
 	compilers/texture/TextureCompiler.cpp
+	compilers/package/PackageCompiler.cpp
 )
 
 set (COMPILER_HEADER
 	compilers/Compiler.h
 	compilers/BundleCompiler.h
+	compilers/mesh/MeshCompiler.h
 	compilers/lua/LuaCompiler.h
 	compilers/texture/TextureCompiler.h
+	compilers/package/PackageCompiler.h
 )
 
 set (CROWN_LIBRARIES)
@@ -381,6 +385,7 @@ if (LINUX)
 		os/linux/Thread.h
 		os/linux/Mutex.h
 		os/linux/Cond.h
+		os/posix/Semaphore.h
 	)
 
 	list (APPEND OS_SRC
@@ -389,20 +394,15 @@ 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
 		renderers/gl/GLRenderer.cpp
-		renderers/gl/GLUtils.cpp
 		renderers/gl/glx/GLContext.cpp
 	)
 
 	list (APPEND RENDERERS_HEADERS
 		renderers/gl/GLRenderer.h
-		renderers/gl/GLUtils.h
 		renderers/gl/glx/GLContext.h
 	)
 
@@ -464,6 +464,7 @@ if (WINDOWS)
 		os/win/Thread.h
 		os/win/Mutex.h
 		os/win/Cond.h
+		os/win/inttypes.h
 	)
 
 	list (APPEND OS_SRC
@@ -477,13 +478,11 @@ if (WINDOWS)
 
 	list (APPEND RENDERERS_SRC
 		renderers/gl/GLRenderer.cpp
-		renderers/gl/GLUtils.cpp
 		renderers/gl/wgl/GLContext.cpp
 	)
 
 	list (APPEND RENDERERS_HEADERS
 		renderers/gl/GLRenderer.h
-		renderers/gl/GLUtils.h
 		renderers/gl/wgl/GLContext.h
 	)
 
@@ -494,7 +493,9 @@ if (WINDOWS)
 		lua51
 	)
 
-	set (COMPILER_FLAGS)
+	set (COMPILER_FLAGS
+		/Wall
+	)
 
 	set (CROWN_MAIN_SRC os/win/main.cpp)
 endif(WINDOWS)
@@ -555,12 +556,16 @@ set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_RPATH}:$ORIGIN")
 add_executable(${CROWN_EXECUTABLE_NAME} ${CROWN_MAIN_SRC})
 target_link_libraries(${CROWN_EXECUTABLE_NAME} crown)
 
+add_executable(crown-linux-renderer-evo os/linux/main2.cpp)
+target_link_libraries(crown-linux-renderer-evo crown)
+
 if (CROWN_BUILD_TESTS)
-	add_subdirectory(tests)
+	#add_subdirectory(tests)
 endif (CROWN_BUILD_TESTS)
 
 install (TARGETS crown DESTINATION bin)
 install (TARGETS ${CROWN_EXECUTABLE_NAME} DESTINATION bin)
+install (TARGETS crown-linux-renderer-evo DESTINATION bin)
 
 #install (FILES ${HEADERS} DESTINATION include/${CMAKE_PROJECT_NAME})
 

+ 12 - 0
engine/Config.h.in

@@ -34,3 +34,15 @@ OTHER DEALINGS IN THE SOFTWARE.
 #cmakedefine CROWN_DEBUG
 #cmakedefine CROWN_DEVELOPMENT
 #cmakedefine CROWN_RELEASE
+
+#define CROWN_MAX_TEXTURE_UNITS		8
+#define CROWN_MAX_TEXTURES			32
+#define CROWN_MAX_RENDER_TARGETS	32
+#define CROWN_MAX_VERTEX_BUFFERS	1024
+#define CROWN_MAX_INDEX_BUFFERS		1024
+#define CROWN_MAX_SHADERS			1024
+#define CROWN_MAX_GPU_PROGRAMS		1024
+#define CROWN_MAX_UNIFORMS			128
+
+// Including NUL character
+#define CROWN_MAX_UNIFORM_NAME_LENGTH	64

+ 1 - 4
engine/Crown.h

@@ -125,11 +125,8 @@ OTHER DEALINGS IN THE SOFTWARE.
 #include "UDPSocket.h"
 
 // Engine/Renderers
-#include "VertexBuffer.h"
-#include "IndexBuffer.h"
 #include "Renderer.h"
-#include "Material.h"
-#include "Texture.h"
+#include "RenderContext.h"
 #include "DebugRenderer.h"
 #include "PixelFormat.h"
 #include "VertexFormat.h"

+ 157 - 27
engine/Device.cpp

@@ -53,6 +53,8 @@ OTHER DEALINGS IN THE SOFTWARE.
 #include "Types.h"
 #include "Bundle.h"
 #include "TempAllocator.h"
+#include "ResourcePackage.h"
+#include "EventBuffer.h"
 
 #if defined(LINUX) || defined(WINDOWS)
 	#include "BundleCompiler.h"
@@ -62,12 +64,14 @@ OTHER DEALINGS IN THE SOFTWARE.
 	#include "ApkFilesystem.h"
 #endif
 
+#define MAX_SUBSYSTEMS_HEAP 16 * 1024 * 1024
+
 namespace crown
 {
 
 //-----------------------------------------------------------------------------
 Device::Device() : 
-	m_allocator(m_subsystems_heap, MAX_SUBSYSTEMS_HEAP),
+	m_allocator(default_allocator(), MAX_SUBSYSTEMS_HEAP),
 
 	m_preferred_window_width(1000),
 	m_preferred_window_height(625),
@@ -80,12 +84,15 @@ Device::Device() :
 
 	m_is_init(false),
 	m_is_running(false),
+	m_is_paused(false),
+	m_is_really_paused(false),
 
 	m_frame_count(0),
 
 	m_last_time(0),
 	m_current_time(0),
 	m_last_delta_time(0.0f),
+	m_time_since_start(0.0),
 
 	m_filesystem(NULL),
 	m_input_manager(NULL),
@@ -93,10 +100,13 @@ Device::Device() :
 	m_renderer(NULL),
 	m_debug_renderer(NULL),
 
+	m_bundle_compiler(NULL),
 	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);
@@ -139,6 +149,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);
 
@@ -175,6 +193,7 @@ bool Device::init(int argc, char** argv)
 	m_input_manager = CE_NEW(m_allocator, InputManager)();
 	Log::d("Input manager created.");
 
+	// default_allocator, maybe it needs fix
 	m_window = CE_NEW(m_allocator, OsWindow)(m_preferred_window_width, m_preferred_window_height, m_parent_window_handle);
 
 	CE_ASSERT(m_window != NULL, "Unable to create the window");
@@ -184,8 +203,9 @@ bool Device::init(int argc, char** argv)
 	Log::d("Window created.");
 
 	// Create renderer
-	m_renderer = Renderer::create(m_allocator);
+	m_renderer = CE_NEW(m_allocator, Renderer)(m_allocator);
 	m_renderer->init();
+	m_renderer_init_request = false;
 	Log::d("Renderer created.");
 
 	// Create debug renderer
@@ -202,22 +222,29 @@ bool Device::init(int argc, char** argv)
 	m_is_init = true;
 	start();
 
-	ResourceId luagame_id = m_resource_manager->load("lua", m_boot_file);
-	m_resource_manager->flush();
-	m_lua_environment->load((LuaResource*) m_resource_manager->data(luagame_id));
-	m_lua_environment->call_global("init", 0);
-	m_resource_manager->unload(luagame_id);
+	// Show main window
+	m_window->show();
+
+	// Execute lua boot file
+	if (m_lua_environment->load_and_execute(m_boot_file))
+	{
+		if (!m_lua_environment->call_global("init", 0))
+		{
+			pause();
+		}
+	}
+	else
+	{
+		pause();
+	}
+
+	Log::d("Total allocated size: %llu", m_allocator.allocated_size());
 
 	if (m_quit_after_init == 1)
 	{
 		stop();
 		shutdown();
 	}
-
-	// Show main window
-	m_window->show();
-
-	return true;
 }
 
 //-----------------------------------------------------------------------------
@@ -260,8 +287,7 @@ void Device::shutdown()
 	if (m_renderer)
 	{
 		m_renderer->shutdown();
-
-		Renderer::destroy(m_allocator, m_renderer);
+		CE_DELETE(m_allocator, m_renderer);
 	}
 
 	Log::i("Releasing Window...");
@@ -287,6 +313,14 @@ void Device::shutdown()
 		CE_DELETE(m_allocator, m_filesystem);
 	}
 
+	#if (defined(LINUX) || defined(WINDOWS)) && (defined(CROWN_DEBUG) || defined(CROWN_DEVELOPMENT))
+		Log::i("Releasing BundleCompiler...");
+		if (m_bundle_compiler)
+		{
+			CE_DELETE(m_allocator, m_bundle_compiler);
+		}
+	#endif
+
 	m_allocator.clear();
 
 	m_is_init = false;
@@ -298,6 +332,12 @@ bool Device::is_init() const
 	return m_is_init;
 }
 
+//-----------------------------------------------------------------------------
+bool Device::is_paused() const
+{
+	return m_is_paused;
+}
+
 //-----------------------------------------------------------------------------
 Filesystem* Device::filesystem()
 {
@@ -385,6 +425,23 @@ void Device::stop()
 	m_is_running = false;
 }
 
+//-----------------------------------------------------------------------------
+void Device::pause()
+{
+	m_is_paused = true;
+
+	Log::d("Engine paused");
+}
+
+//-----------------------------------------------------------------------------
+void Device::unpause()
+{
+	m_is_paused = false;
+	m_is_really_paused = false;
+
+	Log::d("Engine unpaused");
+}
+
 //-----------------------------------------------------------------------------
 bool Device::is_running() const
 {
@@ -404,24 +461,61 @@ float Device::last_delta_time() const
 }
 
 //-----------------------------------------------------------------------------
-void Device::frame()
+double Device::time_since_start() const
+{
+	return m_time_since_start;
+}
+
+//-----------------------------------------------------------------------------
+void Device::frame(cb callback)
 {
 	m_current_time = os::microseconds();
 	m_last_delta_time = (m_current_time - m_last_time) / 1000000.0f;
 	m_last_time = m_current_time;
+	m_time_since_start += m_last_delta_time;
 
-	m_resource_manager->poll_resource_loader();
+	if (!m_is_paused)
+	{
+		m_resource_manager->poll_resource_loader();
 
-	m_window->frame();
-	m_input_manager->frame(frame_count());
-	m_lua_environment->call_global("frame", 1, ARGUMENT_FLOAT, last_delta_time());
+		m_window->frame();
+		m_input_manager->frame(frame_count());
 
-	// m_console_server->execute();
+		if (!m_lua_environment->call_global("frame", 1, ARGUMENT_FLOAT, last_delta_time()))
+		{
+			pause();
+		}
 
-	m_debug_renderer->draw_all();
-	m_renderer->frame();
+		callback(m_last_delta_time);
+		m_renderer->frame();
+	}
 
 	m_frame_count++;
+
+	os_event_buffer()->clear();
+}
+
+//-----------------------------------------------------------------------------
+ResourcePackage* Device::create_resource_package(const char* name)
+{
+	CE_ASSERT_NOT_NULL(name);
+
+	ResourceId package_id = m_resource_manager->load("package", name);
+	m_resource_manager->flush();
+
+	PackageResource* package_res = (PackageResource*) m_resource_manager->data(package_id);
+	ResourcePackage* package = CE_NEW(default_allocator(), ResourcePackage)(*m_resource_manager, package_id, package_res);
+
+	return package;
+}
+
+//-----------------------------------------------------------------------------
+void Device::destroy_resource_package(ResourcePackage* package)
+{
+	CE_ASSERT_NOT_NULL(package);
+
+	m_resource_manager->unload(package->resource_id());
+	CE_DELETE(default_allocator(), package);
 }
 
 //-----------------------------------------------------------------------------
@@ -509,9 +603,24 @@ void Device::parse_command_line(int argc, char** argv)
 //-----------------------------------------------------------------------------
 void Device::check_preferred_settings()
 {
+	if (m_compile == 1)
+	{
+		if (string::strcmp(m_source_dir, "") == 0)
+		{
+			Log::e("You have to specify the source directory when running in compile mode.");
+			exit(EXIT_FAILURE);
+		}
+
+		if (!os::is_absolute_path(m_source_dir))
+		{
+			Log::e("The source directory must be absolute.");
+			exit(EXIT_FAILURE);
+		}
+	}
+
 	if (!os::is_absolute_path(m_bundle_dir))
 	{
-		Log::e("The root path must be absolute.");
+		Log::e("The bundle directory must be absolute.");
 		exit(EXIT_FAILURE);
 	}
 
@@ -594,11 +703,32 @@ void Device::print_help_message()
 	"  --quit-after-init          Quit the engine immediately after the initialization.\n");
 }
 
-Device g_device;
+static Device* g_device = NULL;
+
+//-----------------------------------------------------------------------------
+void init()
+{
+	crown::memory::init();
+	crown::os::init_os();
+	g_device = CE_NEW(default_allocator(), Device);
+}
+
+//-----------------------------------------------------------------------------
+void shutdown()
+{
+	CE_DELETE(default_allocator(), g_device);
+	crown::memory::shutdown();
+}
+
 Device* device()
 {
-	return &g_device;
+	return g_device;
 }
 
-} // namespace crown
+void nothing(float)
+{
+	device()->renderer()->set_layer_clear(0, CLEAR_COLOR | CLEAR_DEPTH, Color4::LIGHTBLUE, 1.0f);
+	device()->renderer()->commit(0);
+}
 
+} // namespace crown

+ 39 - 6
engine/Device.h

@@ -32,8 +32,6 @@ OTHER DEALINGS IN THE SOFTWARE.
 #include "LinearAllocator.h"
 #include "Resource.h"
 
-#define MAX_SUBSYSTEMS_HEAP 1024 * 1024
-
 namespace crown
 {
 
@@ -51,6 +49,10 @@ class Accelerometer;
 class LuaEnvironment;
 class ConsoleServer;
 class BundleCompiler;
+class ResourcePackage;
+
+typedef void (*cb)(float);
+void nothing(float);
 
 /// The Engine.
 /// It is the place where to look for accessing all of
@@ -76,14 +78,19 @@ 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;
 
-	/// Returns the time in milliseconds needed to render
-	/// the last frame
+	/// Returns the time in seconds needed to render the last frame
 	float					last_delta_time() const;
 
+	/// Returns the time in seconds since the first call to start().
+	double					time_since_start() const;
+
 	/// Forces the engine to actually start doing work.
 	void					start();
 
@@ -91,8 +98,24 @@ public:
 	/// and normally terminates the program.
 	void					stop();
 
+	/// Pauses the engine
+	void					pause();
+
+	/// Unpauses the engine
+	void					unpause();
+
 	/// Updates all the subsystems
-	void					frame();
+	void					frame(cb callback);
+	void					frame() { frame(nothing); }
+
+	/// Returns the resource package with the given @a package_name name.
+	ResourcePackage*		create_resource_package(const char* name);
+
+	/// Destroy a previously created resource @a package.
+	/// @note
+	/// To unload the resources loaded by the package, you have to call
+	/// ResourcePackage::unload() first.
+	void					destroy_resource_package(ResourcePackage* package);
 
 	void					compile(const char* bundle_dir, const char* source_dir, const char* resource);
 
@@ -116,6 +139,7 @@ public:
 
 private:
 
+	void					init();
 	void					parse_command_line(int argc, char** argv);
 	void					check_preferred_settings();
 	void					read_engine_settings();
@@ -124,7 +148,6 @@ private:
 private:
 
 	// Used to allocate all subsystems
-	uint8_t					m_subsystems_heap[MAX_SUBSYSTEMS_HEAP];
 	LinearAllocator			m_allocator;
 
 	// Preferred settings
@@ -142,12 +165,16 @@ private:
 
 	bool					m_is_init		: 1;
 	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;
 	uint64_t				m_current_time;
 	float					m_last_delta_time;
+	double					m_time_since_start;
 
 	// Public subsystems
 	Filesystem*				m_filesystem;
@@ -166,13 +193,19 @@ 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 void init();
+CE_EXPORT void shutdown();
 CE_EXPORT Device* device();
 
 } // namespace crown

+ 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

+ 41 - 3
engine/renderers/RenderBuffer.h → engine/EventBuffer.h

@@ -26,12 +26,50 @@ OTHER DEALINGS IN THE SOFTWARE.
 
 #pragma once
 
+#include <cstring>
+
 #include "Types.h"
 
+#define MAX_OS_EVENT_BUFFER_SIZE 1024
+
 namespace crown
 {
 
-// Max number of textures a renderer can hold.
-const uint32_t MAX_RENDER_BUFFERS = 32;
 
-} // 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

+ 2 - 2
engine/FPSSystem.cpp

@@ -170,8 +170,8 @@ void FPSSystem::update(float dt)
 		m_camera->strafe_right(m_camera_speed * dt);
 	}
 
-	device()->renderer()->set_matrix(MT_VIEW, m_camera->view_matrix());
-	device()->renderer()->set_matrix(MT_PROJECTION, m_camera->projection_matrix());
+	// device()->renderer()->set_matrix(MT_VIEW, m_camera->view_matrix());
+	// device()->renderer()->set_matrix(MT_PROJECTION, m_camera->projection_matrix());
 }
 
 //-----------------------------------------------------------------------	

+ 28 - 13
engine/compilers/BundleCompiler.cpp

@@ -57,9 +57,24 @@ bool BundleCompiler::compile(const char* bundle_dir, const char* source_dir)
 		temp.create_directory(bundle_dir);
 	}
 
+	// Copy crown.config to bundle dir
 	DiskFilesystem src_fs(source_dir);
 	DiskFilesystem dst_fs(bundle_dir);
 
+	if (src_fs.is_file("crown.config"))
+	{
+		File* src = src_fs.open("crown.config", FOM_READ);
+		File* dst = dst_fs.open("crown.config", FOM_WRITE);
+		src->copy_to(*dst, src->size());
+		src_fs.close(src);
+		dst_fs.close(dst);
+	}
+	else
+	{
+		Log::d("'crown.config' does not exist.");
+		return false;
+	}
+
 	// Compile all resources
 	for (uint32_t i = 0; i < files.size(); i++)
 	{
@@ -71,27 +86,23 @@ bool BundleCompiler::compile(const char* bundle_dir, const char* source_dir)
 		path::extension(filename, filename_extension, 32);
 		uint32_t resource_type_hash = hash::murmur2_32(filename_extension, string::strlen(filename_extension), 0);
 
-		// Do not compile if curr resource is a config file
+		char out_name[65];
+		snprintf(out_name, 65, "%"PRIx64"", filename_hash);
+
+		// Skip crown.config file
 		if (resource_type_hash == CONFIG_TYPE)
 		{
-			File* src = src_fs.open(filename, FOM_READ);
-			File* dst = dst_fs.open(filename, FOM_WRITE);
-
-			src->copy_to(*dst, src->size());
-
-			src_fs.close(src);
-			dst_fs.close(dst);
-
 			continue;
 		}
 
-		char out_name[65];
-		snprintf(out_name, 65, "%"PRIx64"", filename_hash);
-
 		Log::i("%s <= %s", out_name, filename);
 
 		bool result = false;
-		if (resource_type_hash == TEXTURE_TYPE)
+		if (resource_type_hash == MESH_TYPE)
+		{
+			result = m_mesh.compile(source_dir, bundle_dir, filename, out_name);
+		}
+		else if (resource_type_hash == TEXTURE_TYPE)
 		{
 			result = m_texture.compile(source_dir, bundle_dir, filename, out_name);
 		}
@@ -99,6 +110,10 @@ bool BundleCompiler::compile(const char* bundle_dir, const char* source_dir)
 		{
 			result = m_lua.compile(source_dir, bundle_dir, filename, out_name);
 		}
+		else if (resource_type_hash == PACKAGE_TYPE)
+		{
+			result = m_package.compile(source_dir, bundle_dir, filename, out_name);
+		}
 		else
 		{
 			Log::e("Oops, unknown resource type!");

+ 4 - 0
engine/compilers/BundleCompiler.h

@@ -26,8 +26,10 @@ OTHER DEALINGS IN THE SOFTWARE.
 
 #pragma once
 
+#include "MeshCompiler.h"
 #include "TextureCompiler.h"
 #include "LuaCompiler.h"
+#include "PackageCompiler.h"
 #include "DynamicString.h"
 #include "Vector.h"
 #include "DiskFilesystem.h"
@@ -49,8 +51,10 @@ private:
 
 private:
 
+	MeshCompiler	m_mesh;
 	TextureCompiler	m_texture;
 	LuaCompiler 	m_lua;
+	PackageCompiler m_package;
 };
 
 } // namespace crown

+ 0 - 633
engine/compilers/dae/DAECompiler.cpp

@@ -1,633 +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 <iostream>
-#include <sstream>
-#include "DAECompiler.h"
-
-using tinyxml2::XMLDocument;
-using tinyxml2::XMLElement;
-using tinyxml2::XML_NO_ERROR;
-using tinyxml2::XML_NO_ATTRIBUTE;
-using std::vector;
-using std::cout;
-using std::endl;
-
-namespace crown
-{
-
-//-----------------------------------------------------------------------------
-DAECompiler::DAECompiler()
-{
-
-}
-
-//-----------------------------------------------------------------------------
-DAECompiler::~DAECompiler()
-{
-
-}
-
-//-----------------------------------------------------------------------------
-size_t DAECompiler::compile_impl(const char* resource_path)
-{
-	DAEModel model;
-
-	if (!parse_collada(resource_path, model))
-	{
-		return 0;
-	}
-
-	// Check that polylist is composed of triangles
-	const vector<uint32_t>& vcount = model.geometries[0].mesh.polylist.vcount;
-	for (uint32_t i = 0; i < vcount.size(); i++)
-	{
-		if (vcount[i] != 3)
-		{
-			cout << "Bad polylist: only triangle primitives allowed." << endl;
-			return false;
-		}
-	}
-
-	// Find vertices
-	DAESource vertex_source;
-	if (!find_vertices(model.geometries[0].mesh, vertex_source))
-	{
-		return false;
-	}
-
-	const vector<float>& vertex_vertices = vertex_source.float_array.array;
-	m_vertex_vertices = vertex_vertices;
-
-	vector<uint16_t> vertex_indices;
-	if (!extract_vertex_indices(model.geometries[0].mesh, vertex_indices))
-	{
-		return false;
-	}
-
-	m_vertex_indices = vertex_indices;
-
-	// cout << "Vertices: " << vertex_vertices.size() << endl;
-	// cout << "Indices: " << vertex_indices.size() << endl;
-
-	m_mesh_header.version = MESH_VERSION;
-	m_mesh_header.mesh_count = 1;
-	m_mesh_header.joint_count = 0;
-	//m_mesh_header.padding[0] = 0xCECECECE;
-
-	return sizeof(MeshHeader) +
-			sizeof(uint32_t) + vertex_vertices.size() * sizeof(float) +
-			sizeof(uint32_t) + vertex_indices.size() * sizeof(uint16_t);
-}
-
-//-----------------------------------------------------------------------------
-void DAECompiler::write_impl(std::fstream& out_file)
-{
-	out_file.write((char*) &m_mesh_header, sizeof(MeshHeader));
-
-	uint32_t vertex_count = m_vertex_vertices.size();
-	out_file.write((char*)&vertex_count, sizeof(uint32_t));
-	out_file.write((char*) m_vertex_vertices.data(), m_vertex_vertices.size() * sizeof(float));
-
-	uint32_t triangle_count = m_vertex_indices.size();
-	out_file.write((char*)&triangle_count, sizeof(uint32_t));
-	out_file.write((char*) m_vertex_indices.data(), m_vertex_indices.size() * sizeof(uint16_t));
-}
-
-//-----------------------------------------------------------------------------
-bool DAECompiler::parse_collada(const char* path, DAEModel& m)
-{
-	XMLDocument doc;
-
-	if (doc.LoadFile(path) != XML_NO_ERROR)
-	{
-		cout << "Unable to open '" << path << "'." << endl;
-		return false;
-	}
-
-	// Read root
-	XMLElement* root_node = doc.FirstChildElement("COLLADA");
-	if (root_node == NULL)
-	{
-		cout << "Bad document: missing COLLADA root element." << endl;
-		return false;
-	}
-
-	// Read geometries
-	XMLElement* library_geometries = root_node->FirstChildElement("library_geometries");
-	if (library_geometries == NULL)
-	{
-		cout << "Bad document: missing geometries library." << endl;
-		return false;
-	}
-
-	XMLElement* geometry = library_geometries->FirstChildElement("geometry");
-	if (geometry == NULL)
-	{
-		cout << "Bad document: no geometries found." << endl;
-		return false;
-	}
-
-	for (; geometry != NULL; geometry = geometry->NextSiblingElement("geometry"))
-	{
-		DAEGeometry g;
-		if (parse_geometry(geometry, g))
-		{
-			m.geometries.push_back(g);
-		}
-		else
-		{
-			return false;
-		}
-	}
-
-	return true;
-}
-
-//-----------------------------------------------------------------------------
-bool DAECompiler::parse_geometry(XMLElement* geometry, DAEGeometry& g)
-{
-	// Read geometry id
-	const char* geom_id = geometry->Attribute("id");
-	if (geom_id == NULL)
-	{
-		cout << "Bad geometry: missing 'id' attribute." << endl;
-		return false;
-	}
-
-	g.id = geom_id;
-
-	// Read geometry name
-	const char* geom_name = geometry->Attribute("name");
-	if (geom_name == NULL)
-	{
-		cout << "Bad geometry: missing 'name' attribute." << endl;
-		return false;
-	}
-
-	g.name = geom_name;
-
-	// Read geometry mesh
-	XMLElement* mesh = geometry->FirstChildElement("mesh");
-	if (mesh == NULL)
-	{
-		cout << "Bad geometry: no meshes found." << endl;
-		return false;
-	}
-
-	// Actually, there is more stuff to parse
-	return parse_mesh(mesh, g.mesh);
-}
-
-//-----------------------------------------------------------------------------
-bool DAECompiler::parse_mesh(XMLElement* mesh, DAEMesh& m)
-{
-	/// Read sources
-	XMLElement* source = mesh->FirstChildElement("source");
-	if (source == NULL)
-	{
-		cout << "Bad mesh: no sources found." << endl;
-		return false;
-	}
-
-	for (; source != NULL; source = source->NextSiblingElement("source"))
-	{
-		DAESource s;
-		if (parse_source(source, s))
-		{
-			m.sources.push_back(s);
-		}
-		else
-		{
-			return false;
-		}
-	}
-
-	// Read vertices
-	XMLElement* vertices = mesh->FirstChildElement("vertices");
-	if (vertices == NULL)
-	{
-		cout << "Bad mesh: no vertices found." << endl;
-		return false;
-	}
-
-	if (!parse_vertices(vertices, m.vertices))
-	{
-		return false;
-	}
-
-	// Read polylist
-	XMLElement* polylist = mesh->FirstChildElement("polylist");
-	if (polylist == NULL)
-	{
-		cout << "Bad mesh: no polylist found." << endl;
-		return false;
-	}
-
-	return parse_polylist(polylist, m.polylist);
-}
-
-//-----------------------------------------------------------------------------
-bool DAECompiler::parse_source(XMLElement* source, DAESource& s)
-{
-	// Read source id
-	const char* source_id = source->Attribute("id");
-	if (source_id == NULL)
-	{
-		cout << "Bad source: missing 'id' attribute." << endl;
-		return false;
-	}
-
-	s.id = source_id;
-
-	// Read float array
-	XMLElement* float_array = source->FirstChildElement("float_array");
-	if (float_array == NULL)
-	{
-		cout << "Bad source: no 'float_array' found." << endl;
-		return false;
-	}
-
-	if (!parse_float_array(float_array, s.float_array))
-	{
-		return false;
-	}
-
-	// Read technique
-	XMLElement* technique_common = source->FirstChildElement("technique_common");
-	if (technique_common == NULL)
-	{
-		cout << "Bad source: no 'technique_common' found." << endl;
-		return false;
-	}
-
-	if (!parse_technique_common(technique_common, s.technique_common))
-	{
-		return false;
-	}
-
-	return true;
-}
-
-//-----------------------------------------------------------------------------
-bool DAECompiler::parse_float_array(XMLElement* array, DAEFloatArray& a)
-{
-	// Read float array id
-	const char* float_array_id = array->Attribute("id");
-	if (float_array_id == NULL)
-	{
-		cout << "Bad float array: missing 'id' attribute." << endl;
-		return false;
-	}
-
-	a.id = float_array_id;
-
-	// Read number of floats
-	uint32_t count = 0;
-	if (array->QueryUnsignedAttribute("count", &count) != XML_NO_ERROR)
-	{
-		cout << "Bad float array: missing 'count' attribute." << endl;
-		return false;
-	}
-
-	std::istringstream floats(array->GetText());
-	for (uint32_t i = 0; i < count; i++)
-	{
-		float out = 0.0f;
-		floats >> out;
-		a.array.push_back(out);
-	}
-
-	return true;
-}
-
-//-----------------------------------------------------------------------------
-bool DAECompiler::parse_technique_common(XMLElement* technique, DAETechniqueCommon& t)
-{
-	// Read accessor
-	XMLElement* accessor = technique->FirstChildElement("accessor");
-	if (accessor == NULL)
-	{
-		cout << "Bad technique: no accessors found." << endl;
-		return false;
-	}
-
-	return parse_accessor(accessor, t.accessor);
-}
-
-//-----------------------------------------------------------------------------
-bool DAECompiler::parse_accessor(XMLElement* accessor, DAEAccessor& a)
-{
-	// Read accessor source
-	const char* accessor_source = accessor->Attribute("source");
-	if (accessor_source == NULL)
-	{
-		cout << "Bad accessor: missing 'source' attribute." << endl;
-		return false;
-	}
-
-	// First char is '#'
-	a.source = &accessor_source[1];
-
-	// Read accessor count
-	if (accessor->QueryUnsignedAttribute("count", &a.count) != XML_NO_ERROR)
-	{
-		cout << "Bad accessor: missing 'count' attribute." << endl;
-		return false;
-	}
-
-	// Read accessor stride
-	if (accessor->QueryUnsignedAttribute("stride", &a.stride) != XML_NO_ERROR)
-	{
-		cout << "Bad accessor: missing 'stride' attribute." << endl;
-		return false;
-	}
-
-	// Read params
-	XMLElement* param = accessor->FirstChildElement("param");
-	if (param == NULL)
-	{
-		cout << "Bad accessor: no params found." << endl;
-		return false;
-	}
-
-	for (; param != NULL; param = param->NextSiblingElement("param"))
-	{
-		DAEParam p;
-		if (parse_param(param, p))
-		{
-			a.params.push_back(p);
-		}
-		else
-		{
-			return false;
-		}
-	}
-
-	return true;
-}
-
-//-----------------------------------------------------------------------------
-bool DAECompiler::parse_param(XMLElement* param, DAEParam& p)
-{
-	// Read param name
-	const char* param_name = param->Attribute("name");
-	if (param_name == NULL)
-	{
-		cout << "Bad param: missing 'name' attribute." << endl;
-		return false;
-	}
-
-	p.name = param_name;
-
-	// Read param type
-	const char* param_type = param->Attribute("type");
-	if (param_type == NULL)
-	{
-		cout << "Bad param: missing 'type' attribute." << endl;
-		return false;
-	}
-
-	p.type = param_type;
-
-	return true;
-}
-
-//-----------------------------------------------------------------------------
-bool DAECompiler::parse_vertices(XMLElement* vertices, DAEVertices& v)
-{
-	// Read vertices id
-	const char* vertices_id = vertices->Attribute("id");
-	if (vertices_id == NULL)
-	{
-		cout << "Bad vertices: missing 'id' attribute." << endl;
-		return false;
-	}
-
-	v.id = vertices_id;
-
-	// Read inputs
-	XMLElement* input = vertices->FirstChildElement("input");
-	if (input == NULL)
-	{
-		cout << "Bad vertices: no inputs found." << endl;
-		return false;
-	}
-
-	for (; input != NULL; input = input->NextSiblingElement("input"))
-	{
-		DAEInput i;
-		if (parse_input(input, i))
-		{
-			v.inputs.push_back(i);
-		}
-		else
-		{
-			return false;
-		}
-	}
-
-	return true;
-}
-
-//-----------------------------------------------------------------------------
-bool DAECompiler::parse_input(XMLElement* input, DAEInput& i)
-{
-	// Read input semantic
-	const char* input_semantic = input->Attribute("semantic");
-	if (input_semantic == NULL)
-	{
-		cout << "Bad input: missing 'semantic' attribute." << endl;
-		return false;
-	}
-
-	i.semantic = input_semantic;
-
-	// Read input source
-	const char* input_source = input->Attribute("source");
-	if (input_source == NULL)
-	{
-		cout << "Bad input: missing 'source' attribute." << endl;
-		return false;
-	}
-
-	// First char is '#'
-	i.source = &input_source[1];
-
-	if (input->QueryUnsignedAttribute("offset", &i.offset) == XML_NO_ATTRIBUTE)
-	{
-		i.offset = 0;
-	}
-
-	return true;
-}
-
-//-----------------------------------------------------------------------------
-bool DAECompiler::parse_polylist(XMLElement* polylist, DAEPolylist& p)
-{
-	// Read polylist count
-	if (polylist->QueryUnsignedAttribute("count", &p.count) != XML_NO_ERROR)
-	{
-		cout << "Bad polylist: missing 'count' attribute." << endl;
-		return false;
-	}
-
-	// Read inputs
-	XMLElement* input = polylist->FirstChildElement("input");
-	if (input == NULL)
-	{
-		cout << "Bad polylist: no inputs found." << endl;
-		return false;
-	}
-
-	for (; input != NULL; input = input->NextSiblingElement("input"))
-	{
-		DAEInput i;
-		if (parse_input(input, i))
-		{
-			p.inputs.push_back(i);
-		}
-		else
-		{
-			return false;
-		}
-	}
-
-	// Read vcount
-	XMLElement* vcount = polylist->FirstChildElement("vcount");
-	if (vcount == NULL)
-	{
-		cout << "Bad polylist: no vcount found." << endl;
-		return false;
-	}
-
-	std::istringstream vcount_text(vcount->GetText());
-	uint32_t vcount_item = 0;
-	while (vcount_text >> vcount_item)
-	{
-		p.vcount.push_back(vcount_item);
-	}
-
-	// Read p
-	XMLElement* p_element = polylist->FirstChildElement("p");
-	if (p_element == NULL)
-	{
-		cout << "Bad polylist: no p found." << endl;
-		return false;
-	}
-
-	std::istringstream p_text(p_element->GetText());
-	uint32_t p_item = 0;
-	while (p_text >> p_item)
-	{
-		p.p.push_back(p_item);
-	}
-
-	return true;
-}
-
-//-----------------------------------------------------------------------------
-bool DAECompiler::find_vertices(const DAEMesh& mesh, DAESource& source_out)
-{
-	const vector<DAESource>& sources = mesh.sources;
-	const vector<DAEInput>& inputs = mesh.vertices.inputs;
-
-	for (uint32_t input_i = 0; input_i < inputs.size(); input_i++)
-	{
-		const DAEInput& input = inputs[input_i];
-
-		for (uint32_t source_i = 0; source_i < sources.size(); source_i++)
-		{
-			const DAESource& source = sources[source_i];
-
-			if (input.semantic == "POSITION" && input.source == source.id)
-			{
-				source_out = source;
-				return true;
-			}
-		}
-	}
-
-	cout << "Failed to find 'POSITION' source." << endl;
-	return false;
-}
-
-//-----------------------------------------------------------------------------
-bool DAECompiler::find_normals(const DAEMesh& mesh, DAESource& source_out)
-{
-	const vector<DAESource>& sources = mesh.sources;
-	const vector<DAEInput>& inputs = mesh.polylist.inputs;
-
-	for (uint32_t input_i = 0; input_i < inputs.size(); input_i++)
-	{
-		const DAEInput& input = inputs[input_i];
-
-		for (uint32_t source_i = 0; source_i < sources.size(); source_i++)
-		{
-			const DAESource& source = sources[source_i];
-
-			cout << input.semantic << " " << input.source << " " << source.id << endl;
-			if (input.semantic == "NORMAL" && input.source == source.id)
-			{
-				source_out = source;
-				return true;
-			}
-		}
-	}
-
-	cout << "Failed to find 'NORMAL' source." << endl;
-	return false;
-}
-
-//-----------------------------------------------------------------------------
-bool DAECompiler::extract_vertex_indices(const DAEMesh& mesh, vector<uint16_t>& indices_out)
-{
-	// Find vertices
-	DAESource vertex_source;
-	if (!find_vertices(mesh, vertex_source))
-	{
-		return false;
-	}
-
-	// Read vertices
-	const vector<uint32_t>& primitives = mesh.polylist.p;
-	const vector<float>& vertices = vertex_source.float_array.array;
-
-	// FIXME FIXME FIXME
-	uint32_t offset = 0;
-	uint32_t attribs = mesh.polylist.inputs.size();
-
-	uint32_t prims = 0;
-	while(prims < primitives.size())
-	{
-		indices_out.push_back((uint16_t) primitives[prims]);
-		prims += attribs;
-	}
-
-	return true;
-}
-
-} // namespace crown

+ 0 - 199
engine/compilers/dae/DAECompiler.h

@@ -1,199 +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.
-*/
-
-#pragma once
-
-#include <map>
-#include <string>
-#include <vector>
-
-#include "Compiler.h"
-#include "MeshFormat.h"
-#include "tinyxml2.h"
-
-using tinyxml2::XMLElement;
-using std::vector;
-
-namespace crown
-{
-
-//
-// STRUCT
-// {
-//     FIELD             : SIZE                    COMMENT
-// }
-//
-// MeshHeader [1]
-// {
-//     version           : uint32_t                Version identifier
-//     mesh_count        : uint32_t                Number of meshes in the file
-//     joint_count       : uint32_t                Number of joints in the file
-//     padding           : uint32_t * 16           Reserved
-// }
-// MeshChunk [1, 2, ..., n]
-// {
-//     vertex_count      : uint32_t                Number of vertices in the mesh
-//     vertices          : float * vertex_count    Vertex data
-//
-//     tri_count         : uint32_t                Number of triangles in the mesh
-//     tris              : uint16_t * tri_count    Triangle data as indices into 'vertices'
-// }
-//
-
-// Bump the version whenever a change in the format is made.
-const uint32_t MESH_VERSION = 1;
-
-struct MeshHeader
-{
-	uint32_t	version;
-	uint32_t	mesh_count;
-	uint32_t	joint_count;
-	uint32_t	padding[16];
-};
-
-//-----------------------------------------------------------------------------
-struct DAEFloatArray
-{
-	std::string				id;		// UUID of the array
-	std::vector<float>		array;
-};
-
-//-----------------------------------------------------------------------------
-struct DAEParam
-{
-	std::string				name;
-	std::string				type;
-};
-
-//-----------------------------------------------------------------------------
-struct DAEAccessor
-{
-	std::string				source;
-	uint32_t				count;
-	uint32_t				stride;
-	std::vector<DAEParam>	params;	
-};
-
-//-----------------------------------------------------------------------------
-struct DAETechniqueCommon
-{
-	DAEAccessor				accessor;
-};
-
-//-----------------------------------------------------------------------------
-struct DAESource
-{
-	std::string 			id;					// UUID of the source
-	DAEFloatArray			float_array;		// Array of floats
-	DAETechniqueCommon		technique_common;
-};
-
-//-----------------------------------------------------------------------------
-struct DAEInput
-{
-	std::string				semantic;
-	std::string				source;
-	uint32_t				offset;
-};
-
-//-----------------------------------------------------------------------------
-struct DAEVertices
-{
-	std::string				id;
-	std::vector<DAEInput>	inputs;
-};
-
-//-----------------------------------------------------------------------------
-struct DAEPolylist
-{
-	uint32_t				count;
-	std::vector<DAEInput>	inputs;
-	std::vector<uint32_t>	vcount;
-	std::vector<uint32_t>	p;
-};
-
-//-----------------------------------------------------------------------------
-struct DAEMesh
-{
-	std::vector<DAESource>	sources;
-	DAEVertices				vertices;
-	DAEPolylist				polylist;
-};
-
-//-----------------------------------------------------------------------------
-struct DAEGeometry
-{
-	std::string				id;		// UUID of the geometry
-	std::string				name;	// Name of the geometry
-	DAEMesh					mesh;	// The mesh
-};
-
-//-----------------------------------------------------------------------------
-struct DAEModel
-{
-	std::vector<DAEGeometry>	geometries;
-};
-
-class DAECompiler : public Compiler
-{
-public:
-
-						DAECompiler();
-						~DAECompiler();
-
-	size_t				compile_impl(const char* resource_path);
-	void				write_impl(std::fstream& out_file);
-
-private:
-
-	// The following functions return false if parsing fails, true otherwise
-	static bool			parse_collada(const char* path, DAEModel& m);
-	static bool			parse_geometry(XMLElement* geometry, DAEGeometry& g);
-	static bool			parse_mesh(XMLElement* mesh, DAEMesh& m);
-	static bool			parse_source(XMLElement* source, DAESource& s);
-	static bool			parse_float_array(XMLElement* array, DAEFloatArray& a);
-	static bool			parse_technique_common(XMLElement* technique, DAETechniqueCommon& t);
-	static bool			parse_accessor(XMLElement* accessor, DAEAccessor& a);
-	static bool			parse_param(XMLElement* param, DAEParam& p);
-	static bool			parse_vertices(XMLElement* vertices, DAEVertices& v);
-	static bool			parse_input(XMLElement* input, DAEInput& i);
-	static bool			parse_polylist(XMLElement* polylist, DAEPolylist& p);
-
-	bool				find_vertices(const DAEMesh& mesh, DAESource& source_out);
-	bool				find_normals(const DAEMesh& mesh, DAESource& source_out);
-
-	bool				extract_vertex_indices(const DAEMesh& mesh, vector<uint16_t>& indices_out);
-	bool				extract_vertex_normals(const DAEMesh& mesh, vector<uint32_t>& indices_out);
-
-private:
-
-	MeshHeader			m_mesh_header;
-
-	vector<float>		m_vertex_vertices;
-	vector<uint16_t>	m_vertex_indices;
-};
-
-} // namespace crown

+ 0 - 2099
engine/compilers/dae/tinyxml2.cpp

@@ -1,2099 +0,0 @@
-/*
-Original code by Lee Thomason (www.grinninglizard.com)
-
-This software is provided 'as-is', without any express or implied
-warranty. In no event will the authors be held liable for any
-damages arising from the use of this software.
-
-Permission is granted to anyone to use this software for any
-purpose, including commercial applications, and to alter it and
-redistribute it freely, subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must
-not claim that you wrote the original software. If you use this
-software in a product, an acknowledgment in the product documentation
-would be appreciated but is not required.
-
-2. Altered source versions must be plainly marked as such, and
-must not be misrepresented as being the original software.
-
-3. This notice may not be removed or altered from any source
-distribution.
-*/
-
-#include "tinyxml2.h"
-
-#include <new>		// yes, this one new style header, is in the Android SDK.
-#   ifdef ANDROID_NDK
-#   include <stddef.h>
-#else
-#   include <cstddef>
-#endif
-
-static const char LINE_FEED				= (char)0x0a;			// all line endings are normalized to LF
-static const char LF = LINE_FEED;
-static const char CARRIAGE_RETURN		= (char)0x0d;			// CR gets filtered out
-static const char CR = CARRIAGE_RETURN;
-static const char SINGLE_QUOTE			= '\'';
-static const char DOUBLE_QUOTE			= '\"';
-
-// Bunch of unicode info at:
-//		http://www.unicode.org/faq/utf_bom.html
-//	ef bb bf (Microsoft "lead bytes") - designates UTF-8
-
-static const unsigned char TIXML_UTF_LEAD_0 = 0xefU;
-static const unsigned char TIXML_UTF_LEAD_1 = 0xbbU;
-static const unsigned char TIXML_UTF_LEAD_2 = 0xbfU;
-
-
-#define DELETE_NODE( node )	{			\
-        if ( node ) {						\
-            MemPool* pool = node->_memPool;	\
-            node->~XMLNode();				\
-            pool->Free( node );				\
-        }									\
-    }
-#define DELETE_ATTRIBUTE( attrib ) {		\
-        if ( attrib ) {							\
-            MemPool* pool = attrib->_memPool;	\
-            attrib->~XMLAttribute();			\
-            pool->Free( attrib );				\
-        }										\
-    }
-
-namespace tinyxml2
-{
-
-struct Entity {
-    const char* pattern;
-    int length;
-    char value;
-};
-
-static const int NUM_ENTITIES = 5;
-static const Entity entities[NUM_ENTITIES] = {
-    { "quot", 4,	DOUBLE_QUOTE },
-    { "amp", 3,		'&'  },
-    { "apos", 4,	SINGLE_QUOTE },
-    { "lt",	2, 		'<'	 },
-    { "gt",	2,		'>'	 }
-};
-
-
-StrPair::~StrPair()
-{
-    Reset();
-}
-
-
-void StrPair::Reset()
-{
-    if ( _flags & NEEDS_DELETE ) {
-        delete [] _start;
-    }
-    _flags = 0;
-    _start = 0;
-    _end = 0;
-}
-
-
-void StrPair::SetStr( const char* str, int flags )
-{
-    Reset();
-    size_t len = strlen( str );
-    _start = new char[ len+1 ];
-    memcpy( _start, str, len+1 );
-    _end = _start + len;
-    _flags = flags | NEEDS_DELETE;
-}
-
-
-char* StrPair::ParseText( char* p, const char* endTag, int strFlags )
-{
-    TIXMLASSERT( endTag && *endTag );
-
-    char* start = p;	// fixme: hides a member
-    char  endChar = *endTag;
-    size_t length = strlen( endTag );
-
-    // Inner loop of text parsing.
-    while ( *p ) {
-        if ( *p == endChar && strncmp( p, endTag, length ) == 0 ) {
-            Set( start, p, strFlags );
-            return p + length;
-        }
-        ++p;
-    }
-    return 0;
-}
-
-
-char* StrPair::ParseName( char* p )
-{
-    char* start = p;
-
-    if ( !start || !(*start) ) {
-        return 0;
-    }
-
-    while( *p && ( p == start ? XMLUtil::IsNameStartChar( *p ) : XMLUtil::IsNameChar( *p ) )) {
-        ++p;
-    }
-
-    if ( p > start ) {
-        Set( start, p, 0 );
-        return p;
-    }
-    return 0;
-}
-
-
-void StrPair::CollapseWhitespace()
-{
-    // Trim leading space.
-    _start = XMLUtil::SkipWhiteSpace( _start );
-
-    if ( _start && *_start ) {
-        char* p = _start;	// the read pointer
-        char* q = _start;	// the write pointer
-
-        while( *p ) {
-            if ( XMLUtil::IsWhiteSpace( *p )) {
-                p = XMLUtil::SkipWhiteSpace( p );
-                if ( *p == 0 ) {
-                    break;    // don't write to q; this trims the trailing space.
-                }
-                *q = ' ';
-                ++q;
-            }
-            *q = *p;
-            ++q;
-            ++p;
-        }
-        *q = 0;
-    }
-}
-
-
-const char* StrPair::GetStr()
-{
-    if ( _flags & NEEDS_FLUSH ) {
-        *_end = 0;
-        _flags ^= NEEDS_FLUSH;
-
-        if ( _flags ) {
-            char* p = _start;	// the read pointer
-            char* q = _start;	// the write pointer
-
-            while( p < _end ) {
-                if ( (_flags & NEEDS_NEWLINE_NORMALIZATION) && *p == CR ) {
-                    // CR-LF pair becomes LF
-                    // CR alone becomes LF
-                    // LF-CR becomes LF
-                    if ( *(p+1) == LF ) {
-                        p += 2;
-                    }
-                    else {
-                        ++p;
-                    }
-                    *q++ = LF;
-                }
-                else if ( (_flags & NEEDS_NEWLINE_NORMALIZATION) && *p == LF ) {
-                    if ( *(p+1) == CR ) {
-                        p += 2;
-                    }
-                    else {
-                        ++p;
-                    }
-                    *q++ = LF;
-                }
-                else if ( (_flags & NEEDS_ENTITY_PROCESSING) && *p == '&' ) {
-                    // Entities handled by tinyXML2:
-                    // - special entities in the entity table [in/out]
-                    // - numeric character reference [in]
-                    //   &#20013; or &#x4e2d;
-
-                    if ( *(p+1) == '#' ) {
-                        char buf[10] = { 0 };
-                        int len;
-                        p = const_cast<char*>( XMLUtil::GetCharacterRef( p, buf, &len ) );
-                        for( int i=0; i<len; ++i ) {
-                            *q++ = buf[i];
-                        }
-                        TIXMLASSERT( q <= p );
-                    }
-                    else {
-                        int i=0;
-                        for(; i<NUM_ENTITIES; ++i ) {
-                            if (    strncmp( p+1, entities[i].pattern, entities[i].length ) == 0
-                                    && *(p+entities[i].length+1) == ';' ) {
-                                // Found an entity convert;
-                                *q = entities[i].value;
-                                ++q;
-                                p += entities[i].length + 2;
-                                break;
-                            }
-                        }
-                        if ( i == NUM_ENTITIES ) {
-                            // fixme: treat as error?
-                            ++p;
-                            ++q;
-                        }
-                    }
-                }
-                else {
-                    *q = *p;
-                    ++p;
-                    ++q;
-                }
-            }
-            *q = 0;
-        }
-        // The loop below has plenty going on, and this
-        // is a less useful mode. Break it out.
-        if ( _flags & COLLAPSE_WHITESPACE ) {
-            CollapseWhitespace();
-        }
-        _flags = (_flags & NEEDS_DELETE);
-    }
-    return _start;
-}
-
-
-
-
-// --------- XMLUtil ----------- //
-
-const char* XMLUtil::ReadBOM( const char* p, bool* bom )
-{
-    *bom = false;
-    const unsigned char* pu = reinterpret_cast<const unsigned char*>(p);
-    // Check for BOM:
-    if (    *(pu+0) == TIXML_UTF_LEAD_0
-            && *(pu+1) == TIXML_UTF_LEAD_1
-            && *(pu+2) == TIXML_UTF_LEAD_2 ) {
-        *bom = true;
-        p += 3;
-    }
-    return p;
-}
-
-
-void XMLUtil::ConvertUTF32ToUTF8( unsigned long input, char* output, int* length )
-{
-    const unsigned long BYTE_MASK = 0xBF;
-    const unsigned long BYTE_MARK = 0x80;
-    const unsigned long FIRST_BYTE_MARK[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
-
-    if (input < 0x80) {
-        *length = 1;
-    }
-    else if ( input < 0x800 ) {
-        *length = 2;
-    }
-    else if ( input < 0x10000 ) {
-        *length = 3;
-    }
-    else if ( input < 0x200000 ) {
-        *length = 4;
-    }
-    else {
-        *length = 0;    // This code won't covert this correctly anyway.
-        return;
-    }
-
-    output += *length;
-
-    // Scary scary fall throughs.
-    switch (*length) {
-        case 4:
-            --output;
-            *output = (char)((input | BYTE_MARK) & BYTE_MASK);
-            input >>= 6;
-        case 3:
-            --output;
-            *output = (char)((input | BYTE_MARK) & BYTE_MASK);
-            input >>= 6;
-        case 2:
-            --output;
-            *output = (char)((input | BYTE_MARK) & BYTE_MASK);
-            input >>= 6;
-        case 1:
-            --output;
-            *output = (char)(input | FIRST_BYTE_MARK[*length]);
-        default:
-            break;
-    }
-}
-
-
-const char* XMLUtil::GetCharacterRef( const char* p, char* value, int* length )
-{
-    // Presume an entity, and pull it out.
-    *length = 0;
-
-    if ( *(p+1) == '#' && *(p+2) ) {
-        unsigned long ucs = 0;
-        ptrdiff_t delta = 0;
-        unsigned mult = 1;
-
-        if ( *(p+2) == 'x' ) {
-            // Hexadecimal.
-            if ( !*(p+3) ) {
-                return 0;
-            }
-
-            const char* q = p+3;
-            q = strchr( q, ';' );
-
-            if ( !q || !*q ) {
-                return 0;
-            }
-
-            delta = q-p;
-            --q;
-
-            while ( *q != 'x' ) {
-                if ( *q >= '0' && *q <= '9' ) {
-                    ucs += mult * (*q - '0');
-                }
-                else if ( *q >= 'a' && *q <= 'f' ) {
-                    ucs += mult * (*q - 'a' + 10);
-                }
-                else if ( *q >= 'A' && *q <= 'F' ) {
-                    ucs += mult * (*q - 'A' + 10 );
-                }
-                else {
-                    return 0;
-                }
-                mult *= 16;
-                --q;
-            }
-        }
-        else {
-            // Decimal.
-            if ( !*(p+2) ) {
-                return 0;
-            }
-
-            const char* q = p+2;
-            q = strchr( q, ';' );
-
-            if ( !q || !*q ) {
-                return 0;
-            }
-
-            delta = q-p;
-            --q;
-
-            while ( *q != '#' ) {
-                if ( *q >= '0' && *q <= '9' ) {
-                    ucs += mult * (*q - '0');
-                }
-                else {
-                    return 0;
-                }
-                mult *= 10;
-                --q;
-            }
-        }
-        // convert the UCS to UTF-8
-        ConvertUTF32ToUTF8( ucs, value, length );
-        return p + delta + 1;
-    }
-    return p+1;
-}
-
-
-void XMLUtil::ToStr( int v, char* buffer, int bufferSize )
-{
-    TIXML_SNPRINTF( buffer, bufferSize, "%d", v );
-}
-
-
-void XMLUtil::ToStr( unsigned v, char* buffer, int bufferSize )
-{
-    TIXML_SNPRINTF( buffer, bufferSize, "%u", v );
-}
-
-
-void XMLUtil::ToStr( bool v, char* buffer, int bufferSize )
-{
-    TIXML_SNPRINTF( buffer, bufferSize, "%d", v ? 1 : 0 );
-}
-
-
-void XMLUtil::ToStr( float v, char* buffer, int bufferSize )
-{
-    TIXML_SNPRINTF( buffer, bufferSize, "%f", v );
-}
-
-
-void XMLUtil::ToStr( double v, char* buffer, int bufferSize )
-{
-    TIXML_SNPRINTF( buffer, bufferSize, "%f", v );
-}
-
-
-bool XMLUtil::ToInt( const char* str, int* value )
-{
-    if ( TIXML_SSCANF( str, "%d", value ) == 1 ) {
-        return true;
-    }
-    return false;
-}
-
-bool XMLUtil::ToUnsigned( const char* str, unsigned *value )
-{
-    if ( TIXML_SSCANF( str, "%u", value ) == 1 ) {
-        return true;
-    }
-    return false;
-}
-
-bool XMLUtil::ToBool( const char* str, bool* value )
-{
-    int ival = 0;
-    if ( ToInt( str, &ival )) {
-        *value = (ival==0) ? false : true;
-        return true;
-    }
-    if ( StringEqual( str, "true" ) ) {
-        *value = true;
-        return true;
-    }
-    else if ( StringEqual( str, "false" ) ) {
-        *value = false;
-        return true;
-    }
-    return false;
-}
-
-
-bool XMLUtil::ToFloat( const char* str, float* value )
-{
-    if ( TIXML_SSCANF( str, "%f", value ) == 1 ) {
-        return true;
-    }
-    return false;
-}
-
-bool XMLUtil::ToDouble( const char* str, double* value )
-{
-    if ( TIXML_SSCANF( str, "%lf", value ) == 1 ) {
-        return true;
-    }
-    return false;
-}
-
-
-char* XMLDocument::Identify( char* p, XMLNode** node )
-{
-    XMLNode* returnNode = 0;
-    char* start = p;
-    p = XMLUtil::SkipWhiteSpace( p );
-    if( !p || !*p ) {
-        return p;
-    }
-
-    // What is this thing?
-    // - Elements start with a letter or underscore, but xml is reserved.
-    // - Comments: <!--
-    // - Declaration: <?
-    // - Everything else is unknown to tinyxml.
-    //
-
-    static const char* xmlHeader		= { "<?" };
-    static const char* commentHeader	= { "<!--" };
-    static const char* dtdHeader		= { "<!" };
-    static const char* cdataHeader		= { "<![CDATA[" };
-    static const char* elementHeader	= { "<" };	// and a header for everything else; check last.
-
-    static const int xmlHeaderLen		= 2;
-    static const int commentHeaderLen	= 4;
-    static const int dtdHeaderLen		= 2;
-    static const int cdataHeaderLen		= 9;
-    static const int elementHeaderLen	= 1;
-
-#if defined(_MSC_VER)
-#pragma warning ( push )
-#pragma warning ( disable : 4127 )
-#endif
-    TIXMLASSERT( sizeof( XMLComment ) == sizeof( XMLUnknown ) );		// use same memory pool
-    TIXMLASSERT( sizeof( XMLComment ) == sizeof( XMLDeclaration ) );	// use same memory pool
-#if defined(_MSC_VER)
-#pragma warning (pop)
-#endif
-    if ( XMLUtil::StringEqual( p, xmlHeader, xmlHeaderLen ) ) {
-        returnNode = new (_commentPool.Alloc()) XMLDeclaration( this );
-        returnNode->_memPool = &_commentPool;
-        p += xmlHeaderLen;
-    }
-    else if ( XMLUtil::StringEqual( p, commentHeader, commentHeaderLen ) ) {
-        returnNode = new (_commentPool.Alloc()) XMLComment( this );
-        returnNode->_memPool = &_commentPool;
-        p += commentHeaderLen;
-    }
-    else if ( XMLUtil::StringEqual( p, cdataHeader, cdataHeaderLen ) ) {
-        XMLText* text = new (_textPool.Alloc()) XMLText( this );
-        returnNode = text;
-        returnNode->_memPool = &_textPool;
-        p += cdataHeaderLen;
-        text->SetCData( true );
-    }
-    else if ( XMLUtil::StringEqual( p, dtdHeader, dtdHeaderLen ) ) {
-        returnNode = new (_commentPool.Alloc()) XMLUnknown( this );
-        returnNode->_memPool = &_commentPool;
-        p += dtdHeaderLen;
-    }
-    else if ( XMLUtil::StringEqual( p, elementHeader, elementHeaderLen ) ) {
-        returnNode = new (_elementPool.Alloc()) XMLElement( this );
-        returnNode->_memPool = &_elementPool;
-        p += elementHeaderLen;
-    }
-    else {
-        returnNode = new (_textPool.Alloc()) XMLText( this );
-        returnNode->_memPool = &_textPool;
-        p = start;	// Back it up, all the text counts.
-    }
-
-    *node = returnNode;
-    return p;
-}
-
-
-bool XMLDocument::Accept( XMLVisitor* visitor ) const
-{
-    if ( visitor->VisitEnter( *this ) ) {
-        for ( const XMLNode* node=FirstChild(); node; node=node->NextSibling() ) {
-            if ( !node->Accept( visitor ) ) {
-                break;
-            }
-        }
-    }
-    return visitor->VisitExit( *this );
-}
-
-
-// --------- XMLNode ----------- //
-
-XMLNode::XMLNode( XMLDocument* doc ) :
-    _document( doc ),
-    _parent( 0 ),
-    _firstChild( 0 ), _lastChild( 0 ),
-    _prev( 0 ), _next( 0 ),
-    _memPool( 0 )
-{
-}
-
-
-XMLNode::~XMLNode()
-{
-    DeleteChildren();
-    if ( _parent ) {
-        _parent->Unlink( this );
-    }
-}
-
-
-void XMLNode::SetValue( const char* str, bool staticMem )
-{
-    if ( staticMem ) {
-        _value.SetInternedStr( str );
-    }
-    else {
-        _value.SetStr( str );
-    }
-}
-
-
-void XMLNode::DeleteChildren()
-{
-    while( _firstChild ) {
-        XMLNode* node = _firstChild;
-        Unlink( node );
-
-        DELETE_NODE( node );
-    }
-    _firstChild = _lastChild = 0;
-}
-
-
-void XMLNode::Unlink( XMLNode* child )
-{
-    TIXMLASSERT( child->_parent == this );
-    if ( child == _firstChild ) {
-        _firstChild = _firstChild->_next;
-    }
-    if ( child == _lastChild ) {
-        _lastChild = _lastChild->_prev;
-    }
-
-    if ( child->_prev ) {
-        child->_prev->_next = child->_next;
-    }
-    if ( child->_next ) {
-        child->_next->_prev = child->_prev;
-    }
-    child->_parent = 0;
-}
-
-
-void XMLNode::DeleteChild( XMLNode* node )
-{
-    TIXMLASSERT( node->_parent == this );
-    DELETE_NODE( node );
-}
-
-
-XMLNode* XMLNode::InsertEndChild( XMLNode* addThis )
-{
-    if ( _lastChild ) {
-        TIXMLASSERT( _firstChild );
-        TIXMLASSERT( _lastChild->_next == 0 );
-        _lastChild->_next = addThis;
-        addThis->_prev = _lastChild;
-        _lastChild = addThis;
-
-        addThis->_next = 0;
-    }
-    else {
-        TIXMLASSERT( _firstChild == 0 );
-        _firstChild = _lastChild = addThis;
-
-        addThis->_prev = 0;
-        addThis->_next = 0;
-    }
-    addThis->_parent = this;
-    addThis->_memPool->SetTracked();
-    return addThis;
-}
-
-
-XMLNode* XMLNode::InsertFirstChild( XMLNode* addThis )
-{
-    if ( _firstChild ) {
-        TIXMLASSERT( _lastChild );
-        TIXMLASSERT( _firstChild->_prev == 0 );
-
-        _firstChild->_prev = addThis;
-        addThis->_next = _firstChild;
-        _firstChild = addThis;
-
-        addThis->_prev = 0;
-    }
-    else {
-        TIXMLASSERT( _lastChild == 0 );
-        _firstChild = _lastChild = addThis;
-
-        addThis->_prev = 0;
-        addThis->_next = 0;
-    }
-    addThis->_parent = this;
-    addThis->_memPool->SetTracked();
-    return addThis;
-}
-
-
-XMLNode* XMLNode::InsertAfterChild( XMLNode* afterThis, XMLNode* addThis )
-{
-    TIXMLASSERT( afterThis->_parent == this );
-    if ( afterThis->_parent != this ) {
-        return 0;
-    }
-
-    if ( afterThis->_next == 0 ) {
-        // The last node or the only node.
-        return InsertEndChild( addThis );
-    }
-    addThis->_prev = afterThis;
-    addThis->_next = afterThis->_next;
-    afterThis->_next->_prev = addThis;
-    afterThis->_next = addThis;
-    addThis->_parent = this;
-    addThis->_memPool->SetTracked();
-    return addThis;
-}
-
-
-
-
-const XMLElement* XMLNode::FirstChildElement( const char* value ) const
-{
-    for( XMLNode* node=_firstChild; node; node=node->_next ) {
-        XMLElement* element = node->ToElement();
-        if ( element ) {
-            if ( !value || XMLUtil::StringEqual( element->Name(), value ) ) {
-                return element;
-            }
-        }
-    }
-    return 0;
-}
-
-
-const XMLElement* XMLNode::LastChildElement( const char* value ) const
-{
-    for( XMLNode* node=_lastChild; node; node=node->_prev ) {
-        XMLElement* element = node->ToElement();
-        if ( element ) {
-            if ( !value || XMLUtil::StringEqual( element->Name(), value ) ) {
-                return element;
-            }
-        }
-    }
-    return 0;
-}
-
-
-const XMLElement* XMLNode::NextSiblingElement( const char* value ) const
-{
-    for( XMLNode* element=this->_next; element; element = element->_next ) {
-        if (    element->ToElement()
-                && (!value || XMLUtil::StringEqual( value, element->Value() ))) {
-            return element->ToElement();
-        }
-    }
-    return 0;
-}
-
-
-const XMLElement* XMLNode::PreviousSiblingElement( const char* value ) const
-{
-    for( XMLNode* element=_prev; element; element = element->_prev ) {
-        if (    element->ToElement()
-                && (!value || XMLUtil::StringEqual( value, element->Value() ))) {
-            return element->ToElement();
-        }
-    }
-    return 0;
-}
-
-
-char* XMLNode::ParseDeep( char* p, StrPair* parentEnd )
-{
-    // This is a recursive method, but thinking about it "at the current level"
-    // it is a pretty simple flat list:
-    //		<foo/>
-    //		<!-- comment -->
-    //
-    // With a special case:
-    //		<foo>
-    //		</foo>
-    //		<!-- comment -->
-    //
-    // Where the closing element (/foo) *must* be the next thing after the opening
-    // element, and the names must match. BUT the tricky bit is that the closing
-    // element will be read by the child.
-    //
-    // 'endTag' is the end tag for this node, it is returned by a call to a child.
-    // 'parentEnd' is the end tag for the parent, which is filled in and returned.
-
-    while( p && *p ) {
-        XMLNode* node = 0;
-
-        p = _document->Identify( p, &node );
-        if ( p == 0 || node == 0 ) {
-            break;
-        }
-
-        StrPair endTag;
-        p = node->ParseDeep( p, &endTag );
-        if ( !p ) {
-            DELETE_NODE( node );
-            node = 0;
-            if ( !_document->Error() ) {
-                _document->SetError( XML_ERROR_PARSING, 0, 0 );
-            }
-            break;
-        }
-
-        // We read the end tag. Return it to the parent.
-        if ( node->ToElement() && node->ToElement()->ClosingType() == XMLElement::CLOSING ) {
-            if ( parentEnd ) {
-                *parentEnd = static_cast<XMLElement*>(node)->_value;
-            }
-			node->_memPool->SetTracked();	// created and then immediately deleted.
-            DELETE_NODE( node );
-            return p;
-        }
-
-        // Handle an end tag returned to this level.
-        // And handle a bunch of annoying errors.
-        XMLElement* ele = node->ToElement();
-        if ( ele ) {
-            if ( endTag.Empty() && ele->ClosingType() == XMLElement::OPEN ) {
-                _document->SetError( XML_ERROR_MISMATCHED_ELEMENT, node->Value(), 0 );
-                p = 0;
-            }
-            else if ( !endTag.Empty() && ele->ClosingType() != XMLElement::OPEN ) {
-                _document->SetError( XML_ERROR_MISMATCHED_ELEMENT, node->Value(), 0 );
-                p = 0;
-            }
-            else if ( !endTag.Empty() ) {
-                if ( !XMLUtil::StringEqual( endTag.GetStr(), node->Value() )) {
-                    _document->SetError( XML_ERROR_MISMATCHED_ELEMENT, node->Value(), 0 );
-                    p = 0;
-                }
-            }
-        }
-        if ( p == 0 ) {
-            DELETE_NODE( node );
-            node = 0;
-        }
-        if ( node ) {
-            this->InsertEndChild( node );
-        }
-    }
-    return 0;
-}
-
-// --------- XMLText ---------- //
-char* XMLText::ParseDeep( char* p, StrPair* )
-{
-    const char* start = p;
-    if ( this->CData() ) {
-        p = _value.ParseText( p, "]]>", StrPair::NEEDS_NEWLINE_NORMALIZATION );
-        if ( !p ) {
-            _document->SetError( XML_ERROR_PARSING_CDATA, start, 0 );
-        }
-        return p;
-    }
-    else {
-        int flags = _document->ProcessEntities() ? StrPair::TEXT_ELEMENT : StrPair::TEXT_ELEMENT_LEAVE_ENTITIES;
-        if ( _document->WhitespaceMode() == COLLAPSE_WHITESPACE ) {
-            flags |= StrPair::COLLAPSE_WHITESPACE;
-        }
-
-        p = _value.ParseText( p, "<", flags );
-        if ( !p ) {
-            _document->SetError( XML_ERROR_PARSING_TEXT, start, 0 );
-        }
-        if ( p && *p ) {
-            return p-1;
-        }
-    }
-    return 0;
-}
-
-
-XMLNode* XMLText::ShallowClone( XMLDocument* doc ) const
-{
-    if ( !doc ) {
-        doc = _document;
-    }
-    XMLText* text = doc->NewText( Value() );	// fixme: this will always allocate memory. Intern?
-    text->SetCData( this->CData() );
-    return text;
-}
-
-
-bool XMLText::ShallowEqual( const XMLNode* compare ) const
-{
-    return ( compare->ToText() && XMLUtil::StringEqual( compare->ToText()->Value(), Value() ));
-}
-
-
-bool XMLText::Accept( XMLVisitor* visitor ) const
-{
-    return visitor->Visit( *this );
-}
-
-
-// --------- XMLComment ---------- //
-
-XMLComment::XMLComment( XMLDocument* doc ) : XMLNode( doc )
-{
-}
-
-
-XMLComment::~XMLComment()
-{
-}
-
-
-char* XMLComment::ParseDeep( char* p, StrPair* )
-{
-    // Comment parses as text.
-    const char* start = p;
-    p = _value.ParseText( p, "-->", StrPair::COMMENT );
-    if ( p == 0 ) {
-        _document->SetError( XML_ERROR_PARSING_COMMENT, start, 0 );
-    }
-    return p;
-}
-
-
-XMLNode* XMLComment::ShallowClone( XMLDocument* doc ) const
-{
-    if ( !doc ) {
-        doc = _document;
-    }
-    XMLComment* comment = doc->NewComment( Value() );	// fixme: this will always allocate memory. Intern?
-    return comment;
-}
-
-
-bool XMLComment::ShallowEqual( const XMLNode* compare ) const
-{
-    return ( compare->ToComment() && XMLUtil::StringEqual( compare->ToComment()->Value(), Value() ));
-}
-
-
-bool XMLComment::Accept( XMLVisitor* visitor ) const
-{
-    return visitor->Visit( *this );
-}
-
-
-// --------- XMLDeclaration ---------- //
-
-XMLDeclaration::XMLDeclaration( XMLDocument* doc ) : XMLNode( doc )
-{
-}
-
-
-XMLDeclaration::~XMLDeclaration()
-{
-    //printf( "~XMLDeclaration\n" );
-}
-
-
-char* XMLDeclaration::ParseDeep( char* p, StrPair* )
-{
-    // Declaration parses as text.
-    const char* start = p;
-    p = _value.ParseText( p, "?>", StrPair::NEEDS_NEWLINE_NORMALIZATION );
-    if ( p == 0 ) {
-        _document->SetError( XML_ERROR_PARSING_DECLARATION, start, 0 );
-    }
-    return p;
-}
-
-
-XMLNode* XMLDeclaration::ShallowClone( XMLDocument* doc ) const
-{
-    if ( !doc ) {
-        doc = _document;
-    }
-    XMLDeclaration* dec = doc->NewDeclaration( Value() );	// fixme: this will always allocate memory. Intern?
-    return dec;
-}
-
-
-bool XMLDeclaration::ShallowEqual( const XMLNode* compare ) const
-{
-    return ( compare->ToDeclaration() && XMLUtil::StringEqual( compare->ToDeclaration()->Value(), Value() ));
-}
-
-
-
-bool XMLDeclaration::Accept( XMLVisitor* visitor ) const
-{
-    return visitor->Visit( *this );
-}
-
-// --------- XMLUnknown ---------- //
-
-XMLUnknown::XMLUnknown( XMLDocument* doc ) : XMLNode( doc )
-{
-}
-
-
-XMLUnknown::~XMLUnknown()
-{
-}
-
-
-char* XMLUnknown::ParseDeep( char* p, StrPair* )
-{
-    // Unknown parses as text.
-    const char* start = p;
-
-    p = _value.ParseText( p, ">", StrPair::NEEDS_NEWLINE_NORMALIZATION );
-    if ( !p ) {
-        _document->SetError( XML_ERROR_PARSING_UNKNOWN, start, 0 );
-    }
-    return p;
-}
-
-
-XMLNode* XMLUnknown::ShallowClone( XMLDocument* doc ) const
-{
-    if ( !doc ) {
-        doc = _document;
-    }
-    XMLUnknown* text = doc->NewUnknown( Value() );	// fixme: this will always allocate memory. Intern?
-    return text;
-}
-
-
-bool XMLUnknown::ShallowEqual( const XMLNode* compare ) const
-{
-    return ( compare->ToUnknown() && XMLUtil::StringEqual( compare->ToUnknown()->Value(), Value() ));
-}
-
-
-bool XMLUnknown::Accept( XMLVisitor* visitor ) const
-{
-    return visitor->Visit( *this );
-}
-
-// --------- XMLAttribute ---------- //
-char* XMLAttribute::ParseDeep( char* p, bool processEntities )
-{
-    // Parse using the name rules: bug fix, was using ParseText before
-    p = _name.ParseName( p );
-    if ( !p || !*p ) {
-        return 0;
-    }
-
-    // Skip white space before =
-    p = XMLUtil::SkipWhiteSpace( p );
-    if ( !p || *p != '=' ) {
-        return 0;
-    }
-
-    ++p;	// move up to opening quote
-    p = XMLUtil::SkipWhiteSpace( p );
-    if ( *p != '\"' && *p != '\'' ) {
-        return 0;
-    }
-
-    char endTag[2] = { *p, 0 };
-    ++p;	// move past opening quote
-
-    p = _value.ParseText( p, endTag, processEntities ? StrPair::ATTRIBUTE_VALUE : StrPair::ATTRIBUTE_VALUE_LEAVE_ENTITIES );
-    return p;
-}
-
-
-void XMLAttribute::SetName( const char* n )
-{
-    _name.SetStr( n );
-}
-
-
-XMLError XMLAttribute::QueryIntValue( int* value ) const
-{
-    if ( XMLUtil::ToInt( Value(), value )) {
-        return XML_NO_ERROR;
-    }
-    return XML_WRONG_ATTRIBUTE_TYPE;
-}
-
-
-XMLError XMLAttribute::QueryUnsignedValue( unsigned int* value ) const
-{
-    if ( XMLUtil::ToUnsigned( Value(), value )) {
-        return XML_NO_ERROR;
-    }
-    return XML_WRONG_ATTRIBUTE_TYPE;
-}
-
-
-XMLError XMLAttribute::QueryBoolValue( bool* value ) const
-{
-    if ( XMLUtil::ToBool( Value(), value )) {
-        return XML_NO_ERROR;
-    }
-    return XML_WRONG_ATTRIBUTE_TYPE;
-}
-
-
-XMLError XMLAttribute::QueryFloatValue( float* value ) const
-{
-    if ( XMLUtil::ToFloat( Value(), value )) {
-        return XML_NO_ERROR;
-    }
-    return XML_WRONG_ATTRIBUTE_TYPE;
-}
-
-
-XMLError XMLAttribute::QueryDoubleValue( double* value ) const
-{
-    if ( XMLUtil::ToDouble( Value(), value )) {
-        return XML_NO_ERROR;
-    }
-    return XML_WRONG_ATTRIBUTE_TYPE;
-}
-
-
-void XMLAttribute::SetAttribute( const char* v )
-{
-    _value.SetStr( v );
-}
-
-
-void XMLAttribute::SetAttribute( int v )
-{
-    char buf[BUF_SIZE];
-    XMLUtil::ToStr( v, buf, BUF_SIZE );
-    _value.SetStr( buf );
-}
-
-
-void XMLAttribute::SetAttribute( unsigned v )
-{
-    char buf[BUF_SIZE];
-    XMLUtil::ToStr( v, buf, BUF_SIZE );
-    _value.SetStr( buf );
-}
-
-
-void XMLAttribute::SetAttribute( bool v )
-{
-    char buf[BUF_SIZE];
-    XMLUtil::ToStr( v, buf, BUF_SIZE );
-    _value.SetStr( buf );
-}
-
-void XMLAttribute::SetAttribute( double v )
-{
-    char buf[BUF_SIZE];
-    XMLUtil::ToStr( v, buf, BUF_SIZE );
-    _value.SetStr( buf );
-}
-
-void XMLAttribute::SetAttribute( float v )
-{
-    char buf[BUF_SIZE];
-    XMLUtil::ToStr( v, buf, BUF_SIZE );
-    _value.SetStr( buf );
-}
-
-
-// --------- XMLElement ---------- //
-XMLElement::XMLElement( XMLDocument* doc ) : XMLNode( doc ),
-    _closingType( 0 ),
-    _rootAttribute( 0 )
-{
-}
-
-
-XMLElement::~XMLElement()
-{
-    while( _rootAttribute ) {
-        XMLAttribute* next = _rootAttribute->_next;
-        DELETE_ATTRIBUTE( _rootAttribute );
-        _rootAttribute = next;
-    }
-}
-
-
-XMLAttribute* XMLElement::FindAttribute( const char* name )
-{
-    XMLAttribute* a = 0;
-    for( a=_rootAttribute; a; a = a->_next ) {
-        if ( XMLUtil::StringEqual( a->Name(), name ) ) {
-            return a;
-        }
-    }
-    return 0;
-}
-
-
-const XMLAttribute* XMLElement::FindAttribute( const char* name ) const
-{
-    XMLAttribute* a = 0;
-    for( a=_rootAttribute; a; a = a->_next ) {
-        if ( XMLUtil::StringEqual( a->Name(), name ) ) {
-            return a;
-        }
-    }
-    return 0;
-}
-
-
-const char* XMLElement::Attribute( const char* name, const char* value ) const
-{
-    const XMLAttribute* a = FindAttribute( name );
-    if ( !a ) {
-        return 0;
-    }
-    if ( !value || XMLUtil::StringEqual( a->Value(), value )) {
-        return a->Value();
-    }
-    return 0;
-}
-
-
-const char* XMLElement::GetText() const
-{
-    if ( FirstChild() && FirstChild()->ToText() ) {
-        return FirstChild()->ToText()->Value();
-    }
-    return 0;
-}
-
-
-XMLError XMLElement::QueryIntText( int* ival ) const
-{
-    if ( FirstChild() && FirstChild()->ToText() ) {
-        const char* t = FirstChild()->ToText()->Value();
-        if ( XMLUtil::ToInt( t, ival ) ) {
-            return XML_SUCCESS;
-        }
-        return XML_CAN_NOT_CONVERT_TEXT;
-    }
-    return XML_NO_TEXT_NODE;
-}
-
-
-XMLError XMLElement::QueryUnsignedText( unsigned* uval ) const
-{
-    if ( FirstChild() && FirstChild()->ToText() ) {
-        const char* t = FirstChild()->ToText()->Value();
-        if ( XMLUtil::ToUnsigned( t, uval ) ) {
-            return XML_SUCCESS;
-        }
-        return XML_CAN_NOT_CONVERT_TEXT;
-    }
-    return XML_NO_TEXT_NODE;
-}
-
-
-XMLError XMLElement::QueryBoolText( bool* bval ) const
-{
-    if ( FirstChild() && FirstChild()->ToText() ) {
-        const char* t = FirstChild()->ToText()->Value();
-        if ( XMLUtil::ToBool( t, bval ) ) {
-            return XML_SUCCESS;
-        }
-        return XML_CAN_NOT_CONVERT_TEXT;
-    }
-    return XML_NO_TEXT_NODE;
-}
-
-
-XMLError XMLElement::QueryDoubleText( double* dval ) const
-{
-    if ( FirstChild() && FirstChild()->ToText() ) {
-        const char* t = FirstChild()->ToText()->Value();
-        if ( XMLUtil::ToDouble( t, dval ) ) {
-            return XML_SUCCESS;
-        }
-        return XML_CAN_NOT_CONVERT_TEXT;
-    }
-    return XML_NO_TEXT_NODE;
-}
-
-
-XMLError XMLElement::QueryFloatText( float* fval ) const
-{
-    if ( FirstChild() && FirstChild()->ToText() ) {
-        const char* t = FirstChild()->ToText()->Value();
-        if ( XMLUtil::ToFloat( t, fval ) ) {
-            return XML_SUCCESS;
-        }
-        return XML_CAN_NOT_CONVERT_TEXT;
-    }
-    return XML_NO_TEXT_NODE;
-}
-
-
-
-XMLAttribute* XMLElement::FindOrCreateAttribute( const char* name )
-{
-    XMLAttribute* last = 0;
-    XMLAttribute* attrib = 0;
-    for( attrib = _rootAttribute;
-            attrib;
-            last = attrib, attrib = attrib->_next ) {
-        if ( XMLUtil::StringEqual( attrib->Name(), name ) ) {
-            break;
-        }
-    }
-    if ( !attrib ) {
-        attrib = new (_document->_attributePool.Alloc() ) XMLAttribute();
-        attrib->_memPool = &_document->_attributePool;
-        if ( last ) {
-            last->_next = attrib;
-        }
-        else {
-            _rootAttribute = attrib;
-        }
-        attrib->SetName( name );
-        attrib->_memPool->SetTracked(); // always created and linked.
-    }
-    return attrib;
-}
-
-
-void XMLElement::DeleteAttribute( const char* name )
-{
-    XMLAttribute* prev = 0;
-    for( XMLAttribute* a=_rootAttribute; a; a=a->_next ) {
-        if ( XMLUtil::StringEqual( name, a->Name() ) ) {
-            if ( prev ) {
-                prev->_next = a->_next;
-            }
-            else {
-                _rootAttribute = a->_next;
-            }
-            DELETE_ATTRIBUTE( a );
-            break;
-        }
-        prev = a;
-    }
-}
-
-
-char* XMLElement::ParseAttributes( char* p )
-{
-    const char* start = p;
-    XMLAttribute* prevAttribute = 0;
-
-    // Read the attributes.
-    while( p ) {
-        p = XMLUtil::SkipWhiteSpace( p );
-        if ( !p || !(*p) ) {
-            _document->SetError( XML_ERROR_PARSING_ELEMENT, start, Name() );
-            return 0;
-        }
-
-        // attribute.
-        if (XMLUtil::IsNameStartChar( *p ) ) {
-            XMLAttribute* attrib = new (_document->_attributePool.Alloc() ) XMLAttribute();
-            attrib->_memPool = &_document->_attributePool;
-			attrib->_memPool->SetTracked();
-
-            p = attrib->ParseDeep( p, _document->ProcessEntities() );
-            if ( !p || Attribute( attrib->Name() ) ) {
-                DELETE_ATTRIBUTE( attrib );
-                _document->SetError( XML_ERROR_PARSING_ATTRIBUTE, start, p );
-                return 0;
-            }
-            // There is a minor bug here: if the attribute in the source xml
-            // document is duplicated, it will not be detected and the
-            // attribute will be doubly added. However, tracking the 'prevAttribute'
-            // avoids re-scanning the attribute list. Preferring performance for
-            // now, may reconsider in the future.
-            if ( prevAttribute ) {
-                prevAttribute->_next = attrib;
-            }
-            else {
-                _rootAttribute = attrib;
-            }
-            prevAttribute = attrib;
-        }
-        // end of the tag
-        else if ( *p == '/' && *(p+1) == '>' ) {
-            _closingType = CLOSED;
-            return p+2;	// done; sealed element.
-        }
-        // end of the tag
-        else if ( *p == '>' ) {
-            ++p;
-            break;
-        }
-        else {
-            _document->SetError( XML_ERROR_PARSING_ELEMENT, start, p );
-            return 0;
-        }
-    }
-    return p;
-}
-
-
-//
-//	<ele></ele>
-//	<ele>foo<b>bar</b></ele>
-//
-char* XMLElement::ParseDeep( char* p, StrPair* strPair )
-{
-    // Read the element name.
-    p = XMLUtil::SkipWhiteSpace( p );
-    if ( !p ) {
-        return 0;
-    }
-
-    // The closing element is the </element> form. It is
-    // parsed just like a regular element then deleted from
-    // the DOM.
-    if ( *p == '/' ) {
-        _closingType = CLOSING;
-        ++p;
-    }
-
-    p = _value.ParseName( p );
-    if ( _value.Empty() ) {
-        return 0;
-    }
-
-    p = ParseAttributes( p );
-    if ( !p || !*p || _closingType ) {
-        return p;
-    }
-
-    p = XMLNode::ParseDeep( p, strPair );
-    return p;
-}
-
-
-
-XMLNode* XMLElement::ShallowClone( XMLDocument* doc ) const
-{
-    if ( !doc ) {
-        doc = _document;
-    }
-    XMLElement* element = doc->NewElement( Value() );					// fixme: this will always allocate memory. Intern?
-    for( const XMLAttribute* a=FirstAttribute(); a; a=a->Next() ) {
-        element->SetAttribute( a->Name(), a->Value() );					// fixme: this will always allocate memory. Intern?
-    }
-    return element;
-}
-
-
-bool XMLElement::ShallowEqual( const XMLNode* compare ) const
-{
-    const XMLElement* other = compare->ToElement();
-    if ( other && XMLUtil::StringEqual( other->Value(), Value() )) {
-
-        const XMLAttribute* a=FirstAttribute();
-        const XMLAttribute* b=other->FirstAttribute();
-
-        while ( a && b ) {
-            if ( !XMLUtil::StringEqual( a->Value(), b->Value() ) ) {
-                return false;
-            }
-            a = a->Next();
-            b = b->Next();
-        }
-        if ( a || b ) {
-            // different count
-            return false;
-        }
-        return true;
-    }
-    return false;
-}
-
-
-bool XMLElement::Accept( XMLVisitor* visitor ) const
-{
-    if ( visitor->VisitEnter( *this, _rootAttribute ) ) {
-        for ( const XMLNode* node=FirstChild(); node; node=node->NextSibling() ) {
-            if ( !node->Accept( visitor ) ) {
-                break;
-            }
-        }
-    }
-    return visitor->VisitExit( *this );
-}
-
-
-// --------- XMLDocument ----------- //
-XMLDocument::XMLDocument( bool processEntities, Whitespace whitespace ) :
-    XMLNode( 0 ),
-    _writeBOM( false ),
-    _processEntities( processEntities ),
-    _errorID( XML_NO_ERROR ),
-    _whitespace( whitespace ),
-    _errorStr1( 0 ),
-    _errorStr2( 0 ),
-    _charBuffer( 0 )
-{
-    _document = this;	// avoid warning about 'this' in initializer list
-}
-
-
-XMLDocument::~XMLDocument()
-{
-    DeleteChildren();
-    delete [] _charBuffer;
-
-#if 0
-    _textPool.Trace( "text" );
-    _elementPool.Trace( "element" );
-    _commentPool.Trace( "comment" );
-    _attributePool.Trace( "attribute" );
-#endif
-
-#ifdef DEBUG
-	if ( Error() == false ) {
-		TIXMLASSERT( _elementPool.CurrentAllocs()   == _elementPool.Untracked() );
-		TIXMLASSERT( _attributePool.CurrentAllocs() == _attributePool.Untracked() );
-		TIXMLASSERT( _textPool.CurrentAllocs()      == _textPool.Untracked() );
-		TIXMLASSERT( _commentPool.CurrentAllocs()   == _commentPool.Untracked() );
-	}
-#endif
-}
-
-
-void XMLDocument::Clear()
-{
-    DeleteChildren();
-
-    _errorID = XML_NO_ERROR;
-    _errorStr1 = 0;
-    _errorStr2 = 0;
-
-    delete [] _charBuffer;
-    _charBuffer = 0;
-}
-
-
-XMLElement* XMLDocument::NewElement( const char* name )
-{
-    XMLElement* ele = new (_elementPool.Alloc()) XMLElement( this );
-    ele->_memPool = &_elementPool;
-    ele->SetName( name );
-    return ele;
-}
-
-
-XMLComment* XMLDocument::NewComment( const char* str )
-{
-    XMLComment* comment = new (_commentPool.Alloc()) XMLComment( this );
-    comment->_memPool = &_commentPool;
-    comment->SetValue( str );
-    return comment;
-}
-
-
-XMLText* XMLDocument::NewText( const char* str )
-{
-    XMLText* text = new (_textPool.Alloc()) XMLText( this );
-    text->_memPool = &_textPool;
-    text->SetValue( str );
-    return text;
-}
-
-
-XMLDeclaration* XMLDocument::NewDeclaration( const char* str )
-{
-    XMLDeclaration* dec = new (_commentPool.Alloc()) XMLDeclaration( this );
-    dec->_memPool = &_commentPool;
-    dec->SetValue( str ? str : "xml version=\"1.0\" encoding=\"UTF-8\"" );
-    return dec;
-}
-
-
-XMLUnknown* XMLDocument::NewUnknown( const char* str )
-{
-    XMLUnknown* unk = new (_commentPool.Alloc()) XMLUnknown( this );
-    unk->_memPool = &_commentPool;
-    unk->SetValue( str );
-    return unk;
-}
-
-
-XMLError XMLDocument::LoadFile( const char* filename )
-{
-    Clear();
-    FILE* fp = 0;
-
-#if defined(_MSC_VER) && (_MSC_VER >= 1400 )
-    errno_t err = fopen_s(&fp, filename, "rb" );
-    if ( !fp || err) {
-#else
-    fp = fopen( filename, "rb" );
-    if ( !fp) {
-#endif
-        SetError( XML_ERROR_FILE_NOT_FOUND, filename, 0 );
-        return _errorID;
-    }
-    LoadFile( fp );
-    fclose( fp );
-    return _errorID;
-}
-
-
-XMLError XMLDocument::LoadFile( FILE* fp )
-{
-    Clear();
-
-    fseek( fp, 0, SEEK_END );
-    size_t size = ftell( fp );
-    fseek( fp, 0, SEEK_SET );
-
-    if ( size == 0 ) {
-        SetError( XML_ERROR_EMPTY_DOCUMENT, 0, 0 );
-        return _errorID;
-    }
-
-    _charBuffer = new char[size+1];
-    size_t read = fread( _charBuffer, 1, size, fp );
-    if ( read != size ) {
-        SetError( XML_ERROR_FILE_READ_ERROR, 0, 0 );
-        return _errorID;
-    }
-
-    _charBuffer[size] = 0;
-
-    const char* p = _charBuffer;
-    p = XMLUtil::SkipWhiteSpace( p );
-    p = XMLUtil::ReadBOM( p, &_writeBOM );
-    if ( !p || !*p ) {
-        SetError( XML_ERROR_EMPTY_DOCUMENT, 0, 0 );
-        return _errorID;
-    }
-
-    ParseDeep( _charBuffer + (p-_charBuffer), 0 );
-    return _errorID;
-}
-
-
-XMLError XMLDocument::SaveFile( const char* filename, bool compact )
-{
-    FILE* fp = 0;
-#if defined(_MSC_VER) && (_MSC_VER >= 1400 )
-    errno_t err = fopen_s(&fp, filename, "w" );
-    if ( !fp || err) {
-#else
-    fp = fopen( filename, "w" );
-    if ( !fp) {
-#endif
-        SetError( XML_ERROR_FILE_COULD_NOT_BE_OPENED, filename, 0 );
-        return _errorID;
-    }
-    SaveFile(fp, compact);
-    fclose( fp );
-    return _errorID;
-}
-
-
-XMLError XMLDocument::SaveFile( FILE* fp, bool compact )
-{
-    XMLPrinter stream( fp, compact );
-    Print( &stream );
-    return _errorID;
-}
-
-
-XMLError XMLDocument::Parse( const char* p, size_t len )
-{
-	const char* start = p;
-    Clear();
-
-    if ( !p || !*p ) {
-        SetError( XML_ERROR_EMPTY_DOCUMENT, 0, 0 );
-        return _errorID;
-    }
-    if ( len == (size_t)(-1) ) {
-        len = strlen( p );
-    }
-    _charBuffer = new char[ len+1 ];
-    memcpy( _charBuffer, p, len );
-    _charBuffer[len] = 0;
-
-    p = XMLUtil::SkipWhiteSpace( p );
-    p = XMLUtil::ReadBOM( p, &_writeBOM );
-    if ( !p || !*p ) {
-        SetError( XML_ERROR_EMPTY_DOCUMENT, 0, 0 );
-        return _errorID;
-    }
-
-    ptrdiff_t delta = p - start;	// skip initial whitespace, BOM, etc.
-    ParseDeep( _charBuffer+delta, 0 );
-    return _errorID;
-}
-
-
-void XMLDocument::Print( XMLPrinter* streamer ) const
-{
-    XMLPrinter stdStreamer( stdout );
-    if ( !streamer ) {
-        streamer = &stdStreamer;
-    }
-    Accept( streamer );
-}
-
-
-void XMLDocument::SetError( XMLError error, const char* str1, const char* str2 )
-{
-    _errorID = error;
-    _errorStr1 = str1;
-    _errorStr2 = str2;
-}
-
-
-void XMLDocument::PrintError() const
-{
-    if ( _errorID ) {
-        static const int LEN = 20;
-        char buf1[LEN] = { 0 };
-        char buf2[LEN] = { 0 };
-
-        if ( _errorStr1 ) {
-            TIXML_SNPRINTF( buf1, LEN, "%s", _errorStr1 );
-        }
-        if ( _errorStr2 ) {
-            TIXML_SNPRINTF( buf2, LEN, "%s", _errorStr2 );
-        }
-
-        printf( "XMLDocument error id=%d str1=%s str2=%s\n",
-                _errorID, buf1, buf2 );
-    }
-}
-
-
-XMLPrinter::XMLPrinter( FILE* file, bool compact ) :
-    _elementJustOpened( false ),
-    _firstElement( true ),
-    _fp( file ),
-    _depth( 0 ),
-    _textDepth( -1 ),
-    _processEntities( true ),
-    _compactMode( compact )
-{
-    for( int i=0; i<ENTITY_RANGE; ++i ) {
-        _entityFlag[i] = false;
-        _restrictedEntityFlag[i] = false;
-    }
-    for( int i=0; i<NUM_ENTITIES; ++i ) {
-        TIXMLASSERT( entities[i].value < ENTITY_RANGE );
-        if ( entities[i].value < ENTITY_RANGE ) {
-            _entityFlag[ (int)entities[i].value ] = true;
-        }
-    }
-    _restrictedEntityFlag[(int)'&'] = true;
-    _restrictedEntityFlag[(int)'<'] = true;
-    _restrictedEntityFlag[(int)'>'] = true;	// not required, but consistency is nice
-    _buffer.Push( 0 );
-}
-
-
-void XMLPrinter::Print( const char* format, ... )
-{
-    va_list     va;
-    va_start( va, format );
-
-    if ( _fp ) {
-        vfprintf( _fp, format, va );
-    }
-    else {
-        // This seems brutally complex. Haven't figured out a better
-        // way on windows.
-#ifdef _MSC_VER
-        int len = -1;
-        int expand = 1000;
-        while ( len < 0 ) {
-            len = vsnprintf_s( _accumulator.Mem(), _accumulator.Capacity(), _TRUNCATE, format, va );
-            if ( len < 0 ) {
-                expand *= 3/2;
-                _accumulator.PushArr( expand );
-            }
-        }
-        char* p = _buffer.PushArr( len ) - 1;
-        memcpy( p, _accumulator.Mem(), len+1 );
-#else
-        int len = vsnprintf( 0, 0, format, va );
-        // Close out and re-start the va-args
-        va_end( va );
-        va_start( va, format );
-        char* p = _buffer.PushArr( len ) - 1;
-        vsnprintf( p, len+1, format, va );
-#endif
-    }
-    va_end( va );
-}
-
-
-void XMLPrinter::PrintSpace( int depth )
-{
-    for( int i=0; i<depth; ++i ) {
-        Print( "    " );
-    }
-}
-
-
-void XMLPrinter::PrintString( const char* p, bool restricted )
-{
-    // Look for runs of bytes between entities to print.
-    const char* q = p;
-    const bool* flag = restricted ? _restrictedEntityFlag : _entityFlag;
-
-    if ( _processEntities ) {
-        while ( *q ) {
-            // Remember, char is sometimes signed. (How many times has that bitten me?)
-            if ( *q > 0 && *q < ENTITY_RANGE ) {
-                // Check for entities. If one is found, flush
-                // the stream up until the entity, write the
-                // entity, and keep looking.
-                if ( flag[(unsigned)(*q)] ) {
-                    while ( p < q ) {
-                        Print( "%c", *p );
-                        ++p;
-                    }
-                    for( int i=0; i<NUM_ENTITIES; ++i ) {
-                        if ( entities[i].value == *q ) {
-                            Print( "&%s;", entities[i].pattern );
-                            break;
-                        }
-                    }
-                    ++p;
-                }
-            }
-            ++q;
-        }
-    }
-    // Flush the remaining string. This will be the entire
-    // string if an entity wasn't found.
-    if ( !_processEntities || (q-p > 0) ) {
-        Print( "%s", p );
-    }
-}
-
-
-void XMLPrinter::PushHeader( bool writeBOM, bool writeDec )
-{
-    if ( writeBOM ) {
-		static const unsigned char bom[] = { TIXML_UTF_LEAD_0, TIXML_UTF_LEAD_1, TIXML_UTF_LEAD_2, 0 };
-        Print( "%s", bom );
-    }
-    if ( writeDec ) {
-        PushDeclaration( "xml version=\"1.0\"" );
-    }
-}
-
-
-void XMLPrinter::OpenElement( const char* name )
-{
-    if ( _elementJustOpened ) {
-        SealElement();
-    }
-    _stack.Push( name );
-
-    if ( _textDepth < 0 && !_firstElement && !_compactMode ) {
-        Print( "\n" );
-        PrintSpace( _depth );
-    }
-
-    Print( "<%s", name );
-    _elementJustOpened = true;
-    _firstElement = false;
-    ++_depth;
-}
-
-
-void XMLPrinter::PushAttribute( const char* name, const char* value )
-{
-    TIXMLASSERT( _elementJustOpened );
-    Print( " %s=\"", name );
-    PrintString( value, false );
-    Print( "\"" );
-}
-
-
-void XMLPrinter::PushAttribute( const char* name, int v )
-{
-    char buf[BUF_SIZE];
-    XMLUtil::ToStr( v, buf, BUF_SIZE );
-    PushAttribute( name, buf );
-}
-
-
-void XMLPrinter::PushAttribute( const char* name, unsigned v )
-{
-    char buf[BUF_SIZE];
-    XMLUtil::ToStr( v, buf, BUF_SIZE );
-    PushAttribute( name, buf );
-}
-
-
-void XMLPrinter::PushAttribute( const char* name, bool v )
-{
-    char buf[BUF_SIZE];
-    XMLUtil::ToStr( v, buf, BUF_SIZE );
-    PushAttribute( name, buf );
-}
-
-
-void XMLPrinter::PushAttribute( const char* name, double v )
-{
-    char buf[BUF_SIZE];
-    XMLUtil::ToStr( v, buf, BUF_SIZE );
-    PushAttribute( name, buf );
-}
-
-
-void XMLPrinter::CloseElement()
-{
-    --_depth;
-    const char* name = _stack.Pop();
-
-    if ( _elementJustOpened ) {
-        Print( "/>" );
-    }
-    else {
-        if ( _textDepth < 0 && !_compactMode) {
-            Print( "\n" );
-            PrintSpace( _depth );
-        }
-        Print( "</%s>", name );
-    }
-
-    if ( _textDepth == _depth ) {
-        _textDepth = -1;
-    }
-    if ( _depth == 0 && !_compactMode) {
-        Print( "\n" );
-    }
-    _elementJustOpened = false;
-}
-
-
-void XMLPrinter::SealElement()
-{
-    _elementJustOpened = false;
-    Print( ">" );
-}
-
-
-void XMLPrinter::PushText( const char* text, bool cdata )
-{
-    _textDepth = _depth-1;
-
-    if ( _elementJustOpened ) {
-        SealElement();
-    }
-    if ( cdata ) {
-        Print( "<![CDATA[" );
-        Print( "%s", text );
-        Print( "]]>" );
-    }
-    else {
-        PrintString( text, true );
-    }
-}
-
-void XMLPrinter::PushText( int value )
-{
-    char buf[BUF_SIZE];
-    XMLUtil::ToStr( value, buf, BUF_SIZE );
-    PushText( buf, false );
-}
-
-
-void XMLPrinter::PushText( unsigned value )
-{
-    char buf[BUF_SIZE];
-    XMLUtil::ToStr( value, buf, BUF_SIZE );
-    PushText( buf, false );
-}
-
-
-void XMLPrinter::PushText( bool value )
-{
-    char buf[BUF_SIZE];
-    XMLUtil::ToStr( value, buf, BUF_SIZE );
-    PushText( buf, false );
-}
-
-
-void XMLPrinter::PushText( float value )
-{
-    char buf[BUF_SIZE];
-    XMLUtil::ToStr( value, buf, BUF_SIZE );
-    PushText( buf, false );
-}
-
-
-void XMLPrinter::PushText( double value )
-{
-    char buf[BUF_SIZE];
-    XMLUtil::ToStr( value, buf, BUF_SIZE );
-    PushText( buf, false );
-}
-
-
-void XMLPrinter::PushComment( const char* comment )
-{
-    if ( _elementJustOpened ) {
-        SealElement();
-    }
-    if ( _textDepth < 0 && !_firstElement && !_compactMode) {
-        Print( "\n" );
-        PrintSpace( _depth );
-    }
-    _firstElement = false;
-    Print( "<!--%s-->", comment );
-}
-
-
-void XMLPrinter::PushDeclaration( const char* value )
-{
-    if ( _elementJustOpened ) {
-        SealElement();
-    }
-    if ( _textDepth < 0 && !_firstElement && !_compactMode) {
-        Print( "\n" );
-        PrintSpace( _depth );
-    }
-    _firstElement = false;
-    Print( "<?%s?>", value );
-}
-
-
-void XMLPrinter::PushUnknown( const char* value )
-{
-    if ( _elementJustOpened ) {
-        SealElement();
-    }
-    if ( _textDepth < 0 && !_firstElement && !_compactMode) {
-        Print( "\n" );
-        PrintSpace( _depth );
-    }
-    _firstElement = false;
-    Print( "<!%s>", value );
-}
-
-
-bool XMLPrinter::VisitEnter( const XMLDocument& doc )
-{
-    _processEntities = doc.ProcessEntities();
-    if ( doc.HasBOM() ) {
-        PushHeader( true, false );
-    }
-    return true;
-}
-
-
-bool XMLPrinter::VisitEnter( const XMLElement& element, const XMLAttribute* attribute )
-{
-    OpenElement( element.Name() );
-    while ( attribute ) {
-        PushAttribute( attribute->Name(), attribute->Value() );
-        attribute = attribute->Next();
-    }
-    return true;
-}
-
-
-bool XMLPrinter::VisitExit( const XMLElement& )
-{
-    CloseElement();
-    return true;
-}
-
-
-bool XMLPrinter::Visit( const XMLText& text )
-{
-    PushText( text.Value(), text.CData() );
-    return true;
-}
-
-
-bool XMLPrinter::Visit( const XMLComment& comment )
-{
-    PushComment( comment.Value() );
-    return true;
-}
-
-bool XMLPrinter::Visit( const XMLDeclaration& declaration )
-{
-    PushDeclaration( declaration.Value() );
-    return true;
-}
-
-
-bool XMLPrinter::Visit( const XMLUnknown& unknown )
-{
-    PushUnknown( unknown.Value() );
-    return true;
-}
-
-}   // namespace tinyxml2
-

+ 0 - 1968
engine/compilers/dae/tinyxml2.h

@@ -1,1968 +0,0 @@
-/*
-Original code by Lee Thomason (www.grinninglizard.com)
-
-This software is provided 'as-is', without any express or implied
-warranty. In no event will the authors be held liable for any
-damages arising from the use of this software.
-
-Permission is granted to anyone to use this software for any
-purpose, including commercial applications, and to alter it and
-redistribute it freely, subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must
-not claim that you wrote the original software. If you use this
-software in a product, an acknowledgment in the product documentation
-would be appreciated but is not required.
-
-2. Altered source versions must be plainly marked as such, and
-must not be misrepresented as being the original software.
-
-3. This notice may not be removed or altered from any source
-distribution.
-*/
-
-#ifndef TINYXML2_INCLUDED
-#define TINYXML2_INCLUDED
-
-#if defined(ANDROID_NDK) || defined(__BORLANDC__)
-#   include <ctype.h>
-#   include <limits.h>
-#   include <stdio.h>
-#   include <stdlib.h>
-#   include <string.h>
-#   include <stdarg.h>
-#else
-#   include <cctype>
-#   include <climits>
-#   include <cstdio>
-#   include <cstdlib>
-#   include <cstring>
-#   include <cstdarg>
-#endif
-
-/*
-   TODO: intern strings instead of allocation.
-*/
-/*
-	gcc:
-        g++ -Wall -DDEBUG tinyxml2.cpp xmltest.cpp -o gccxmltest.exe
-
-    Formatting, Artistic Style:
-        AStyle.exe --style=1tbs --indent-switches --break-closing-brackets --indent-preprocessor tinyxml2.cpp tinyxml2.h
-*/
-
-#if defined( _DEBUG ) || defined( DEBUG ) || defined (__DEBUG__)
-#   ifndef DEBUG
-#       define DEBUG
-#   endif
-#endif
-
-
-#if defined(DEBUG)
-#   if defined(_MSC_VER)
-#       define TIXMLASSERT( x )           if ( !(x)) { __debugbreak(); } //if ( !(x)) WinDebugBreak()
-#   elif defined (ANDROID_NDK)
-#       include <android/log.h>
-#       define TIXMLASSERT( x )           if ( !(x)) { __android_log_assert( "assert", "grinliz", "ASSERT in '%s' at %d.", __FILE__, __LINE__ ); }
-#   else
-#       include <assert.h>
-#       define TIXMLASSERT                assert
-#   endif
-#   else
-#       define TIXMLASSERT( x )           {}
-#endif
-
-
-#if defined(_MSC_VER) && (_MSC_VER >= 1400 )
-// Microsoft visual studio, version 2005 and higher.
-/*int _snprintf_s(
-   char *buffer,
-   size_t sizeOfBuffer,
-   size_t count,
-   const char *format [,
-	  argument] ...
-);*/
-inline int TIXML_SNPRINTF( char* buffer, size_t size, const char* format, ... )
-{
-    va_list va;
-    va_start( va, format );
-    int result = vsnprintf_s( buffer, size, _TRUNCATE, format, va );
-    va_end( va );
-    return result;
-}
-#define TIXML_SSCANF   sscanf_s
-#else
-// GCC version 3 and higher
-//#warning( "Using sn* functions." )
-#define TIXML_SNPRINTF snprintf
-#define TIXML_SSCANF   sscanf
-#endif
-
-static const int TIXML2_MAJOR_VERSION = 1;
-static const int TIXML2_MINOR_VERSION = 0;
-static const int TIXML2_PATCH_VERSION = 11;
-
-namespace tinyxml2
-{
-class XMLDocument;
-class XMLElement;
-class XMLAttribute;
-class XMLComment;
-class XMLNode;
-class XMLText;
-class XMLDeclaration;
-class XMLUnknown;
-
-class XMLPrinter;
-
-/*
-	A class that wraps strings. Normally stores the start and end
-	pointers into the XML file itself, and will apply normalization
-	and entity translation if actually read. Can also store (and memory
-	manage) a traditional char[]
-*/
-class StrPair
-{
-public:
-    enum {
-        NEEDS_ENTITY_PROCESSING			= 0x01,
-        NEEDS_NEWLINE_NORMALIZATION		= 0x02,
-        COLLAPSE_WHITESPACE	                = 0x04,
-
-        TEXT_ELEMENT		            	= NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,
-        TEXT_ELEMENT_LEAVE_ENTITIES		= NEEDS_NEWLINE_NORMALIZATION,
-        ATTRIBUTE_NAME		            	= 0,
-        ATTRIBUTE_VALUE		            	= NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,
-        ATTRIBUTE_VALUE_LEAVE_ENTITIES  	= NEEDS_NEWLINE_NORMALIZATION,
-        COMMENT				        = NEEDS_NEWLINE_NORMALIZATION
-    };
-
-    StrPair() : _flags( 0 ), _start( 0 ), _end( 0 ) {}
-    ~StrPair();
-
-    void Set( char* start, char* end, int flags ) {
-        Reset();
-        _start  = start;
-        _end    = end;
-        _flags  = flags | NEEDS_FLUSH;
-    }
-
-    const char* GetStr();
-
-    bool Empty() const {
-        return _start == _end;
-    }
-
-    void SetInternedStr( const char* str ) {
-        Reset();
-        _start = const_cast<char*>(str);
-    }
-
-    void SetStr( const char* str, int flags=0 );
-
-    char* ParseText( char* in, const char* endTag, int strFlags );
-    char* ParseName( char* in );
-
-private:
-    void Reset();
-    void CollapseWhitespace();
-
-    enum {
-        NEEDS_FLUSH = 0x100,
-        NEEDS_DELETE = 0x200
-    };
-
-    // After parsing, if *_end != 0, it can be set to zero.
-    int     _flags;
-    char*   _start;
-    char*   _end;
-};
-
-
-/*
-	A dynamic array of Plain Old Data. Doesn't support constructors, etc.
-	Has a small initial memory pool, so that low or no usage will not
-	cause a call to new/delete
-*/
-template <class T, int INIT>
-class DynArray
-{
-public:
-    DynArray< T, INIT >() {
-        _mem = _pool;
-        _allocated = INIT;
-        _size = 0;
-    }
-
-    ~DynArray() {
-        if ( _mem != _pool ) {
-            delete [] _mem;
-        }
-    }
-
-    void Push( T t ) {
-        EnsureCapacity( _size+1 );
-        _mem[_size++] = t;
-    }
-
-    T* PushArr( int count ) {
-        EnsureCapacity( _size+count );
-        T* ret = &_mem[_size];
-        _size += count;
-        return ret;
-    }
-
-    T Pop() {
-        return _mem[--_size];
-    }
-
-    void PopArr( int count ) {
-        TIXMLASSERT( _size >= count );
-        _size -= count;
-    }
-
-    bool Empty() const					{
-        return _size == 0;
-    }
-
-    T& operator[](int i)				{
-        TIXMLASSERT( i>= 0 && i < _size );
-        return _mem[i];
-    }
-
-    const T& operator[](int i) const	{
-        TIXMLASSERT( i>= 0 && i < _size );
-        return _mem[i];
-    }
-
-    int Size() const					{
-        return _size;
-    }
-
-    int Capacity() const				{
-        return _allocated;
-    }
-
-    const T* Mem() const				{
-        return _mem;
-    }
-
-    T* Mem()							{
-        return _mem;
-    }
-
-private:
-    void EnsureCapacity( int cap ) {
-        if ( cap > _allocated ) {
-            int newAllocated = cap * 2;
-            T* newMem = new T[newAllocated];
-            memcpy( newMem, _mem, sizeof(T)*_size );	// warning: not using constructors, only works for PODs
-            if ( _mem != _pool ) {
-                delete [] _mem;
-            }
-            _mem = newMem;
-            _allocated = newAllocated;
-        }
-    }
-
-    T*  _mem;
-    T   _pool[INIT];
-    int _allocated;		// objects allocated
-    int _size;			// number objects in use
-};
-
-
-/*
-	Parent virtual class of a pool for fast allocation
-	and deallocation of objects.
-*/
-class MemPool
-{
-public:
-    MemPool() {}
-    virtual ~MemPool() {}
-
-    virtual int ItemSize() const = 0;
-    virtual void* Alloc() = 0;
-    virtual void Free( void* ) = 0;
-    virtual void SetTracked() = 0;
-};
-
-
-/*
-	Template child class to create pools of the correct type.
-*/
-template< int SIZE >
-class MemPoolT : public MemPool
-{
-public:
-    MemPoolT() : _root(0), _currentAllocs(0), _nAllocs(0), _maxAllocs(0), _nUntracked(0)	{}
-    ~MemPoolT() {
-        // Delete the blocks.
-        for( int i=0; i<_blockPtrs.Size(); ++i ) {
-            delete _blockPtrs[i];
-        }
-    }
-
-    virtual int ItemSize() const	{
-        return SIZE;
-    }
-    int CurrentAllocs() const		{
-        return _currentAllocs;
-    }
-
-    virtual void* Alloc() {
-        if ( !_root ) {
-            // Need a new block.
-            Block* block = new Block();
-            _blockPtrs.Push( block );
-
-            for( int i=0; i<COUNT-1; ++i ) {
-                block->chunk[i].next = &block->chunk[i+1];
-            }
-            block->chunk[COUNT-1].next = 0;
-            _root = block->chunk;
-        }
-        void* result = _root;
-        _root = _root->next;
-
-        ++_currentAllocs;
-        if ( _currentAllocs > _maxAllocs ) {
-            _maxAllocs = _currentAllocs;
-        }
-        _nAllocs++;
-        _nUntracked++;
-        return result;
-    }
-    virtual void Free( void* mem ) {
-        if ( !mem ) {
-            return;
-        }
-        --_currentAllocs;
-        Chunk* chunk = (Chunk*)mem;
-#ifdef DEBUG
-        memset( chunk, 0xfe, sizeof(Chunk) );
-#endif
-        chunk->next = _root;
-        _root = chunk;
-    }
-    void Trace( const char* name ) {
-        printf( "Mempool %s watermark=%d [%dk] current=%d size=%d nAlloc=%d blocks=%d\n",
-                name, _maxAllocs, _maxAllocs*SIZE/1024, _currentAllocs, SIZE, _nAllocs, _blockPtrs.Size() );
-    }
-
-    void SetTracked() {
-        _nUntracked--;
-    }
-
-    int Untracked() const {
-        return _nUntracked;
-    }
-
-	// This number is perf sensitive. 4k seems like a good tradeoff on my machine.
-	// The test file is large, 170k.
-	// Release:		VS2010 gcc(no opt)
-	//		1k:		4000
-	//		2k:		4000
-	//		4k:		3900	21000
-	//		16k:	5200
-	//		32k:	4300
-	//		64k:	4000	21000
-    enum { COUNT = (4*1024)/SIZE }; // Some compilers do not accept to use COUNT in private part if COUNT is private
-
-private:
-    union Chunk {
-        Chunk*  next;
-        char    mem[SIZE];
-    };
-    struct Block {
-        Chunk chunk[COUNT];
-    };
-    DynArray< Block*, 10 > _blockPtrs;
-    Chunk* _root;
-
-    int _currentAllocs;
-    int _nAllocs;
-    int _maxAllocs;
-    int _nUntracked;
-};
-
-
-
-/**
-	Implements the interface to the "Visitor pattern" (see the Accept() method.)
-	If you call the Accept() method, it requires being passed a XMLVisitor
-	class to handle callbacks. For nodes that contain other nodes (Document, Element)
-	you will get called with a VisitEnter/VisitExit pair. Nodes that are always leafs
-	are simply called with Visit().
-
-	If you return 'true' from a Visit method, recursive parsing will continue. If you return
-	false, <b>no children of this node or its siblings</b> will be visited.
-
-	All flavors of Visit methods have a default implementation that returns 'true' (continue
-	visiting). You need to only override methods that are interesting to you.
-
-	Generally Accept() is called on the XMLDocument, although all nodes support visiting.
-
-	You should never change the document from a callback.
-
-	@sa XMLNode::Accept()
-*/
-class XMLVisitor
-{
-public:
-    virtual ~XMLVisitor() {}
-
-    /// Visit a document.
-    virtual bool VisitEnter( const XMLDocument& /*doc*/ )			{
-        return true;
-    }
-    /// Visit a document.
-    virtual bool VisitExit( const XMLDocument& /*doc*/ )			{
-        return true;
-    }
-
-    /// Visit an element.
-    virtual bool VisitEnter( const XMLElement& /*element*/, const XMLAttribute* /*firstAttribute*/ )	{
-        return true;
-    }
-    /// Visit an element.
-    virtual bool VisitExit( const XMLElement& /*element*/ )			{
-        return true;
-    }
-
-    /// Visit a declaration.
-    virtual bool Visit( const XMLDeclaration& /*declaration*/ )		{
-        return true;
-    }
-    /// Visit a text node.
-    virtual bool Visit( const XMLText& /*text*/ )					{
-        return true;
-    }
-    /// Visit a comment node.
-    virtual bool Visit( const XMLComment& /*comment*/ )				{
-        return true;
-    }
-    /// Visit an unknown node.
-    virtual bool Visit( const XMLUnknown& /*unknown*/ )				{
-        return true;
-    }
-};
-
-
-/*
-	Utility functionality.
-*/
-class XMLUtil
-{
-public:
-    // Anything in the high order range of UTF-8 is assumed to not be whitespace. This isn't
-    // correct, but simple, and usually works.
-    static const char* SkipWhiteSpace( const char* p )	{
-        while( !IsUTF8Continuation(*p) && isspace( *reinterpret_cast<const unsigned char*>(p) ) ) {
-            ++p;
-        }
-        return p;
-    }
-    static char* SkipWhiteSpace( char* p )				{
-        while( !IsUTF8Continuation(*p) && isspace( *reinterpret_cast<unsigned char*>(p) ) )		{
-            ++p;
-        }
-        return p;
-    }
-    static bool IsWhiteSpace( char p )					{
-        return !IsUTF8Continuation(p) && isspace( static_cast<unsigned char>(p) );
-    }
-    
-    inline static bool IsNameStartChar( unsigned char ch ) {
-        return ( ( ch < 128 ) ? isalpha( ch ) : 1 )
-               || ch == ':'
-               || ch == '_';
-    }
-    
-    inline static bool IsNameChar( unsigned char ch ) {
-        return IsNameStartChar( ch )
-               || isdigit( ch )
-               || ch == '.'
-               || ch == '-';
-    }
-
-    inline static bool StringEqual( const char* p, const char* q, int nChar=INT_MAX )  {
-        int n = 0;
-        if ( p == q ) {
-            return true;
-        }
-        while( *p && *q && *p == *q && n<nChar ) {
-            ++p;
-            ++q;
-            ++n;
-        }
-        if ( (n == nChar) || ( *p == 0 && *q == 0 ) ) {
-            return true;
-        }
-        return false;
-    }
-    
-    inline static int IsUTF8Continuation( const char p ) {
-        return p & 0x80;
-    }
-
-    static const char* ReadBOM( const char* p, bool* hasBOM );
-    // p is the starting location,
-    // the UTF-8 value of the entity will be placed in value, and length filled in.
-    static const char* GetCharacterRef( const char* p, char* value, int* length );
-    static void ConvertUTF32ToUTF8( unsigned long input, char* output, int* length );
-
-    // converts primitive types to strings
-    static void ToStr( int v, char* buffer, int bufferSize );
-    static void ToStr( unsigned v, char* buffer, int bufferSize );
-    static void ToStr( bool v, char* buffer, int bufferSize );
-    static void ToStr( float v, char* buffer, int bufferSize );
-    static void ToStr( double v, char* buffer, int bufferSize );
-
-    // converts strings to primitive types
-    static bool	ToInt( const char* str, int* value );
-    static bool ToUnsigned( const char* str, unsigned* value );
-    static bool	ToBool( const char* str, bool* value );
-    static bool	ToFloat( const char* str, float* value );
-    static bool ToDouble( const char* str, double* value );
-};
-
-
-/** XMLNode is a base class for every object that is in the
-	XML Document Object Model (DOM), except XMLAttributes.
-	Nodes have siblings, a parent, and children which can
-	be navigated. A node is always in a XMLDocument.
-	The type of a XMLNode can be queried, and it can
-	be cast to its more defined type.
-
-	A XMLDocument allocates memory for all its Nodes.
-	When the XMLDocument gets deleted, all its Nodes
-	will also be deleted.
-
-	@verbatim
-	A Document can contain:	Element	(container or leaf)
-							Comment (leaf)
-							Unknown (leaf)
-							Declaration( leaf )
-
-	An Element can contain:	Element (container or leaf)
-							Text	(leaf)
-							Attributes (not on tree)
-							Comment (leaf)
-							Unknown (leaf)
-
-	@endverbatim
-*/
-class XMLNode
-{
-    friend class XMLDocument;
-    friend class XMLElement;
-public:
-
-    /// Get the XMLDocument that owns this XMLNode.
-    const XMLDocument* GetDocument() const	{
-        return _document;
-    }
-    /// Get the XMLDocument that owns this XMLNode.
-    XMLDocument* GetDocument()				{
-        return _document;
-    }
-
-    /// Safely cast to an Element, or null.
-    virtual XMLElement*		ToElement()		{
-        return 0;
-    }
-    /// Safely cast to Text, or null.
-    virtual XMLText*		ToText()		{
-        return 0;
-    }
-    /// Safely cast to a Comment, or null.
-    virtual XMLComment*		ToComment()		{
-        return 0;
-    }
-    /// Safely cast to a Document, or null.
-    virtual XMLDocument*	ToDocument()	{
-        return 0;
-    }
-    /// Safely cast to a Declaration, or null.
-    virtual XMLDeclaration*	ToDeclaration()	{
-        return 0;
-    }
-    /// Safely cast to an Unknown, or null.
-    virtual XMLUnknown*		ToUnknown()		{
-        return 0;
-    }
-
-    virtual const XMLElement*		ToElement() const		{
-        return 0;
-    }
-    virtual const XMLText*			ToText() const			{
-        return 0;
-    }
-    virtual const XMLComment*		ToComment() const		{
-        return 0;
-    }
-    virtual const XMLDocument*		ToDocument() const		{
-        return 0;
-    }
-    virtual const XMLDeclaration*	ToDeclaration() const	{
-        return 0;
-    }
-    virtual const XMLUnknown*		ToUnknown() const		{
-        return 0;
-    }
-
-    /** The meaning of 'value' changes for the specific type.
-    	@verbatim
-    	Document:	empty
-    	Element:	name of the element
-    	Comment:	the comment text
-    	Unknown:	the tag contents
-    	Text:		the text string
-    	@endverbatim
-    */
-    const char* Value() const			{
-        return _value.GetStr();
-    }
-
-    /** Set the Value of an XML node.
-    	@sa Value()
-    */
-    void SetValue( const char* val, bool staticMem=false );
-
-    /// Get the parent of this node on the DOM.
-    const XMLNode*	Parent() const			{
-        return _parent;
-    }
-
-    XMLNode* Parent()						{
-        return _parent;
-    }
-
-    /// Returns true if this node has no children.
-    bool NoChildren() const					{
-        return !_firstChild;
-    }
-
-    /// Get the first child node, or null if none exists.
-    const XMLNode*  FirstChild() const		{
-        return _firstChild;
-    }
-
-    XMLNode*		FirstChild()			{
-        return _firstChild;
-    }
-
-    /** Get the first child element, or optionally the first child
-        element with the specified name.
-    */
-    const XMLElement* FirstChildElement( const char* value=0 ) const;
-
-    XMLElement* FirstChildElement( const char* value=0 )	{
-        return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->FirstChildElement( value ));
-    }
-
-    /// Get the last child node, or null if none exists.
-    const XMLNode*	LastChild() const						{
-        return _lastChild;
-    }
-
-    XMLNode*		LastChild()								{
-        return const_cast<XMLNode*>(const_cast<const XMLNode*>(this)->LastChild() );
-    }
-
-    /** Get the last child element or optionally the last child
-        element with the specified name.
-    */
-    const XMLElement* LastChildElement( const char* value=0 ) const;
-
-    XMLElement* LastChildElement( const char* value=0 )	{
-        return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->LastChildElement(value) );
-    }
-
-    /// Get the previous (left) sibling node of this node.
-    const XMLNode*	PreviousSibling() const					{
-        return _prev;
-    }
-
-    XMLNode*	PreviousSibling()							{
-        return _prev;
-    }
-
-    /// Get the previous (left) sibling element of this node, with an optionally supplied name.
-    const XMLElement*	PreviousSiblingElement( const char* value=0 ) const ;
-
-    XMLElement*	PreviousSiblingElement( const char* value=0 ) {
-        return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->PreviousSiblingElement( value ) );
-    }
-
-    /// Get the next (right) sibling node of this node.
-    const XMLNode*	NextSibling() const						{
-        return _next;
-    }
-
-    XMLNode*	NextSibling()								{
-        return _next;
-    }
-
-    /// Get the next (right) sibling element of this node, with an optionally supplied name.
-    const XMLElement*	NextSiblingElement( const char* value=0 ) const;
-
-    XMLElement*	NextSiblingElement( const char* value=0 )	{
-        return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->NextSiblingElement( value ) );
-    }
-
-    /**
-    	Add a child node as the last (right) child.
-    */
-    XMLNode* InsertEndChild( XMLNode* addThis );
-
-    XMLNode* LinkEndChild( XMLNode* addThis )	{
-        return InsertEndChild( addThis );
-    }
-    /**
-    	Add a child node as the first (left) child.
-    */
-    XMLNode* InsertFirstChild( XMLNode* addThis );
-    /**
-    	Add a node after the specified child node.
-    */
-    XMLNode* InsertAfterChild( XMLNode* afterThis, XMLNode* addThis );
-
-    /**
-    	Delete all the children of this node.
-    */
-    void DeleteChildren();
-
-    /**
-    	Delete a child of this node.
-    */
-    void DeleteChild( XMLNode* node );
-
-    /**
-    	Make a copy of this node, but not its children.
-    	You may pass in a Document pointer that will be
-    	the owner of the new Node. If the 'document' is
-    	null, then the node returned will be allocated
-    	from the current Document. (this->GetDocument())
-
-    	Note: if called on a XMLDocument, this will return null.
-    */
-    virtual XMLNode* ShallowClone( XMLDocument* document ) const = 0;
-
-    /**
-    	Test if 2 nodes are the same, but don't test children.
-    	The 2 nodes do not need to be in the same Document.
-
-    	Note: if called on a XMLDocument, this will return false.
-    */
-    virtual bool ShallowEqual( const XMLNode* compare ) const = 0;
-
-    /** Accept a hierarchical visit of the nodes in the TinyXML-2 DOM. Every node in the
-    	XML tree will be conditionally visited and the host will be called back
-    	via the XMLVisitor interface.
-
-    	This is essentially a SAX interface for TinyXML-2. (Note however it doesn't re-parse
-    	the XML for the callbacks, so the performance of TinyXML-2 is unchanged by using this
-    	interface versus any other.)
-
-    	The interface has been based on ideas from:
-
-    	- http://www.saxproject.org/
-    	- http://c2.com/cgi/wiki?HierarchicalVisitorPattern
-
-    	Which are both good references for "visiting".
-
-    	An example of using Accept():
-    	@verbatim
-    	XMLPrinter printer;
-    	tinyxmlDoc.Accept( &printer );
-    	const char* xmlcstr = printer.CStr();
-    	@endverbatim
-    */
-    virtual bool Accept( XMLVisitor* visitor ) const = 0;
-
-    // internal
-    virtual char* ParseDeep( char*, StrPair* );
-
-protected:
-    XMLNode( XMLDocument* );
-    virtual ~XMLNode();
-    XMLNode( const XMLNode& );	// not supported
-    XMLNode& operator=( const XMLNode& );	// not supported
-
-    XMLDocument*	_document;
-    XMLNode*		_parent;
-    mutable StrPair	_value;
-
-    XMLNode*		_firstChild;
-    XMLNode*		_lastChild;
-
-    XMLNode*		_prev;
-    XMLNode*		_next;
-
-private:
-    MemPool*		_memPool;
-    void Unlink( XMLNode* child );
-};
-
-
-/** XML text.
-
-	Note that a text node can have child element nodes, for example:
-	@verbatim
-	<root>This is <b>bold</b></root>
-	@endverbatim
-
-	A text node can have 2 ways to output the next. "normal" output
-	and CDATA. It will default to the mode it was parsed from the XML file and
-	you generally want to leave it alone, but you can change the output mode with
-	SetCData() and query it with CData().
-*/
-class XMLText : public XMLNode
-{
-    friend class XMLBase;
-    friend class XMLDocument;
-public:
-    virtual bool Accept( XMLVisitor* visitor ) const;
-
-    virtual XMLText* ToText()			{
-        return this;
-    }
-    virtual const XMLText* ToText() const	{
-        return this;
-    }
-
-    /// Declare whether this should be CDATA or standard text.
-    void SetCData( bool isCData )			{
-        _isCData = isCData;
-    }
-    /// Returns true if this is a CDATA text element.
-    bool CData() const						{
-        return _isCData;
-    }
-
-    char* ParseDeep( char*, StrPair* endTag );
-    virtual XMLNode* ShallowClone( XMLDocument* document ) const;
-    virtual bool ShallowEqual( const XMLNode* compare ) const;
-
-protected:
-    XMLText( XMLDocument* doc )	: XMLNode( doc ), _isCData( false )	{}
-    virtual ~XMLText()												{}
-    XMLText( const XMLText& );	// not supported
-    XMLText& operator=( const XMLText& );	// not supported
-
-private:
-    bool _isCData;
-};
-
-
-/** An XML Comment. */
-class XMLComment : public XMLNode
-{
-    friend class XMLDocument;
-public:
-    virtual XMLComment*	ToComment()					{
-        return this;
-    }
-    virtual const XMLComment* ToComment() const		{
-        return this;
-    }
-
-    virtual bool Accept( XMLVisitor* visitor ) const;
-
-    char* ParseDeep( char*, StrPair* endTag );
-    virtual XMLNode* ShallowClone( XMLDocument* document ) const;
-    virtual bool ShallowEqual( const XMLNode* compare ) const;
-
-protected:
-    XMLComment( XMLDocument* doc );
-    virtual ~XMLComment();
-    XMLComment( const XMLComment& );	// not supported
-    XMLComment& operator=( const XMLComment& );	// not supported
-
-private:
-};
-
-
-/** In correct XML the declaration is the first entry in the file.
-	@verbatim
-		<?xml version="1.0" standalone="yes"?>
-	@endverbatim
-
-	TinyXML-2 will happily read or write files without a declaration,
-	however.
-
-	The text of the declaration isn't interpreted. It is parsed
-	and written as a string.
-*/
-class XMLDeclaration : public XMLNode
-{
-    friend class XMLDocument;
-public:
-    virtual XMLDeclaration*	ToDeclaration()					{
-        return this;
-    }
-    virtual const XMLDeclaration* ToDeclaration() const		{
-        return this;
-    }
-
-    virtual bool Accept( XMLVisitor* visitor ) const;
-
-    char* ParseDeep( char*, StrPair* endTag );
-    virtual XMLNode* ShallowClone( XMLDocument* document ) const;
-    virtual bool ShallowEqual( const XMLNode* compare ) const;
-
-protected:
-    XMLDeclaration( XMLDocument* doc );
-    virtual ~XMLDeclaration();
-    XMLDeclaration( const XMLDeclaration& );	// not supported
-    XMLDeclaration& operator=( const XMLDeclaration& );	// not supported
-};
-
-
-/** Any tag that TinyXML-2 doesn't recognize is saved as an
-	unknown. It is a tag of text, but should not be modified.
-	It will be written back to the XML, unchanged, when the file
-	is saved.
-
-	DTD tags get thrown into XMLUnknowns.
-*/
-class XMLUnknown : public XMLNode
-{
-    friend class XMLDocument;
-public:
-    virtual XMLUnknown*	ToUnknown()					{
-        return this;
-    }
-    virtual const XMLUnknown* ToUnknown() const		{
-        return this;
-    }
-
-    virtual bool Accept( XMLVisitor* visitor ) const;
-
-    char* ParseDeep( char*, StrPair* endTag );
-    virtual XMLNode* ShallowClone( XMLDocument* document ) const;
-    virtual bool ShallowEqual( const XMLNode* compare ) const;
-
-protected:
-    XMLUnknown( XMLDocument* doc );
-    virtual ~XMLUnknown();
-    XMLUnknown( const XMLUnknown& );	// not supported
-    XMLUnknown& operator=( const XMLUnknown& );	// not supported
-};
-
-
-enum XMLError {
-    XML_NO_ERROR = 0,
-    XML_SUCCESS = 0,
-
-    XML_NO_ATTRIBUTE,
-    XML_WRONG_ATTRIBUTE_TYPE,
-
-    XML_ERROR_FILE_NOT_FOUND,
-    XML_ERROR_FILE_COULD_NOT_BE_OPENED,
-    XML_ERROR_FILE_READ_ERROR,
-    XML_ERROR_ELEMENT_MISMATCH,
-    XML_ERROR_PARSING_ELEMENT,
-    XML_ERROR_PARSING_ATTRIBUTE,
-    XML_ERROR_IDENTIFYING_TAG,
-    XML_ERROR_PARSING_TEXT,
-    XML_ERROR_PARSING_CDATA,
-    XML_ERROR_PARSING_COMMENT,
-    XML_ERROR_PARSING_DECLARATION,
-    XML_ERROR_PARSING_UNKNOWN,
-    XML_ERROR_EMPTY_DOCUMENT,
-    XML_ERROR_MISMATCHED_ELEMENT,
-    XML_ERROR_PARSING,
-
-    XML_CAN_NOT_CONVERT_TEXT,
-    XML_NO_TEXT_NODE
-};
-
-
-/** An attribute is a name-value pair. Elements have an arbitrary
-	number of attributes, each with a unique name.
-
-	@note The attributes are not XMLNodes. You may only query the
-	Next() attribute in a list.
-*/
-class XMLAttribute
-{
-    friend class XMLElement;
-public:
-    /// The name of the attribute.
-    const char* Name() const {
-        return _name.GetStr();
-    }
-    /// The value of the attribute.
-    const char* Value() const {
-        return _value.GetStr();
-    }
-    /// The next attribute in the list.
-    const XMLAttribute* Next() const {
-        return _next;
-    }
-
-    /** IntValue interprets the attribute as an integer, and returns the value.
-        If the value isn't an integer, 0 will be returned. There is no error checking;
-    	use QueryIntValue() if you need error checking.
-    */
-    int		 IntValue() const				{
-        int i=0;
-        QueryIntValue( &i );
-        return i;
-    }
-    /// Query as an unsigned integer. See IntValue()
-    unsigned UnsignedValue() const			{
-        unsigned i=0;
-        QueryUnsignedValue( &i );
-        return i;
-    }
-    /// Query as a boolean. See IntValue()
-    bool	 BoolValue() const				{
-        bool b=false;
-        QueryBoolValue( &b );
-        return b;
-    }
-    /// Query as a double. See IntValue()
-    double 	 DoubleValue() const			{
-        double d=0;
-        QueryDoubleValue( &d );
-        return d;
-    }
-    /// Query as a float. See IntValue()
-    float	 FloatValue() const				{
-        float f=0;
-        QueryFloatValue( &f );
-        return f;
-    }
-
-    /** QueryIntValue interprets the attribute as an integer, and returns the value
-    	in the provided parameter. The function will return XML_NO_ERROR on success,
-    	and XML_WRONG_ATTRIBUTE_TYPE if the conversion is not successful.
-    */
-    XMLError QueryIntValue( int* value ) const;
-    /// See QueryIntValue
-    XMLError QueryUnsignedValue( unsigned int* value ) const;
-    /// See QueryIntValue
-    XMLError QueryBoolValue( bool* value ) const;
-    /// See QueryIntValue
-    XMLError QueryDoubleValue( double* value ) const;
-    /// See QueryIntValue
-    XMLError QueryFloatValue( float* value ) const;
-
-    /// Set the attribute to a string value.
-    void SetAttribute( const char* value );
-    /// Set the attribute to value.
-    void SetAttribute( int value );
-    /// Set the attribute to value.
-    void SetAttribute( unsigned value );
-    /// Set the attribute to value.
-    void SetAttribute( bool value );
-    /// Set the attribute to value.
-    void SetAttribute( double value );
-    /// Set the attribute to value.
-    void SetAttribute( float value );
-
-private:
-    enum { BUF_SIZE = 200 };
-
-    XMLAttribute() : _next( 0 ), _memPool( 0 ) {}
-    virtual ~XMLAttribute()	{}
-
-    XMLAttribute( const XMLAttribute& );	// not supported
-    void operator=( const XMLAttribute& );	// not supported
-    void SetName( const char* name );
-
-    char* ParseDeep( char* p, bool processEntities );
-
-    mutable StrPair _name;
-    mutable StrPair _value;
-    XMLAttribute*   _next;
-    MemPool*        _memPool;
-};
-
-
-/** The element is a container class. It has a value, the element name,
-	and can contain other elements, text, comments, and unknowns.
-	Elements also contain an arbitrary number of attributes.
-*/
-class XMLElement : public XMLNode
-{
-    friend class XMLBase;
-    friend class XMLDocument;
-public:
-    /// Get the name of an element (which is the Value() of the node.)
-    const char* Name() const		{
-        return Value();
-    }
-    /// Set the name of the element.
-    void SetName( const char* str, bool staticMem=false )	{
-        SetValue( str, staticMem );
-    }
-
-    virtual XMLElement* ToElement()				{
-        return this;
-    }
-    virtual const XMLElement* ToElement() const {
-        return this;
-    }
-    virtual bool Accept( XMLVisitor* visitor ) const;
-
-    /** Given an attribute name, Attribute() returns the value
-    	for the attribute of that name, or null if none
-    	exists. For example:
-
-    	@verbatim
-    	const char* value = ele->Attribute( "foo" );
-    	@endverbatim
-
-    	The 'value' parameter is normally null. However, if specified,
-    	the attribute will only be returned if the 'name' and 'value'
-    	match. This allow you to write code:
-
-    	@verbatim
-    	if ( ele->Attribute( "foo", "bar" ) ) callFooIsBar();
-    	@endverbatim
-
-    	rather than:
-    	@verbatim
-    	if ( ele->Attribute( "foo" ) ) {
-    		if ( strcmp( ele->Attribute( "foo" ), "bar" ) == 0 ) callFooIsBar();
-    	}
-    	@endverbatim
-    */
-    const char* Attribute( const char* name, const char* value=0 ) const;
-
-    /** Given an attribute name, IntAttribute() returns the value
-    	of the attribute interpreted as an integer. 0 will be
-    	returned if there is an error. For a method with error
-    	checking, see QueryIntAttribute()
-    */
-    int		 IntAttribute( const char* name ) const		{
-        int i=0;
-        QueryIntAttribute( name, &i );
-        return i;
-    }
-    /// See IntAttribute()
-    unsigned UnsignedAttribute( const char* name ) const {
-        unsigned i=0;
-        QueryUnsignedAttribute( name, &i );
-        return i;
-    }
-    /// See IntAttribute()
-    bool	 BoolAttribute( const char* name ) const	{
-        bool b=false;
-        QueryBoolAttribute( name, &b );
-        return b;
-    }
-    /// See IntAttribute()
-    double 	 DoubleAttribute( const char* name ) const	{
-        double d=0;
-        QueryDoubleAttribute( name, &d );
-        return d;
-    }
-    /// See IntAttribute()
-    float	 FloatAttribute( const char* name ) const	{
-        float f=0;
-        QueryFloatAttribute( name, &f );
-        return f;
-    }
-
-    /** Given an attribute name, QueryIntAttribute() returns
-    	XML_NO_ERROR, XML_WRONG_ATTRIBUTE_TYPE if the conversion
-    	can't be performed, or XML_NO_ATTRIBUTE if the attribute
-    	doesn't exist. If successful, the result of the conversion
-    	will be written to 'value'. If not successful, nothing will
-    	be written to 'value'. This allows you to provide default
-    	value:
-
-    	@verbatim
-    	int value = 10;
-    	QueryIntAttribute( "foo", &value );		// if "foo" isn't found, value will still be 10
-    	@endverbatim
-    */
-    XMLError QueryIntAttribute( const char* name, int* value ) const				{
-        const XMLAttribute* a = FindAttribute( name );
-        if ( !a ) {
-            return XML_NO_ATTRIBUTE;
-        }
-        return a->QueryIntValue( value );
-    }
-    /// See QueryIntAttribute()
-    XMLError QueryUnsignedAttribute( const char* name, unsigned int* value ) const	{
-        const XMLAttribute* a = FindAttribute( name );
-        if ( !a ) {
-            return XML_NO_ATTRIBUTE;
-        }
-        return a->QueryUnsignedValue( value );
-    }
-    /// See QueryIntAttribute()
-    XMLError QueryBoolAttribute( const char* name, bool* value ) const				{
-        const XMLAttribute* a = FindAttribute( name );
-        if ( !a ) {
-            return XML_NO_ATTRIBUTE;
-        }
-        return a->QueryBoolValue( value );
-    }
-    /// See QueryIntAttribute()
-    XMLError QueryDoubleAttribute( const char* name, double* value ) const			{
-        const XMLAttribute* a = FindAttribute( name );
-        if ( !a ) {
-            return XML_NO_ATTRIBUTE;
-        }
-        return a->QueryDoubleValue( value );
-    }
-    /// See QueryIntAttribute()
-    XMLError QueryFloatAttribute( const char* name, float* value ) const			{
-        const XMLAttribute* a = FindAttribute( name );
-        if ( !a ) {
-            return XML_NO_ATTRIBUTE;
-        }
-        return a->QueryFloatValue( value );
-    }
-
-	
-    /** Given an attribute name, QueryAttribute() returns
-    	XML_NO_ERROR, XML_WRONG_ATTRIBUTE_TYPE if the conversion
-    	can't be performed, or XML_NO_ATTRIBUTE if the attribute
-    	doesn't exist. It is overloaded for the primitive types,
-		and is a generally more convenient replacement of
-		QueryIntAttribute() and related functions.
-		
-		If successful, the result of the conversion
-    	will be written to 'value'. If not successful, nothing will
-    	be written to 'value'. This allows you to provide default
-    	value:
-
-    	@verbatim
-    	int value = 10;
-    	QueryAttribute( "foo", &value );		// if "foo" isn't found, value will still be 10
-    	@endverbatim
-    */
-	int QueryAttribute( const char* name, int* value ) const {
-		return QueryIntAttribute( name, value );
-	}
-
-	int QueryAttribute( const char* name, unsigned int* value ) const {
-		return QueryUnsignedAttribute( name, value );
-	}
-
-	int QueryAttribute( const char* name, bool* value ) const {
-		return QueryBoolAttribute( name, value );
-	}
-
-	int QueryAttribute( const char* name, double* value ) const {
-		return QueryDoubleAttribute( name, value );
-	}
-
-	int QueryAttribute( const char* name, float* value ) const {
-		return QueryFloatAttribute( name, value );
-	}
-
-	/// Sets the named attribute to value.
-    void SetAttribute( const char* name, const char* value )	{
-        XMLAttribute* a = FindOrCreateAttribute( name );
-        a->SetAttribute( value );
-    }
-    /// Sets the named attribute to value.
-    void SetAttribute( const char* name, int value )			{
-        XMLAttribute* a = FindOrCreateAttribute( name );
-        a->SetAttribute( value );
-    }
-    /// Sets the named attribute to value.
-    void SetAttribute( const char* name, unsigned value )		{
-        XMLAttribute* a = FindOrCreateAttribute( name );
-        a->SetAttribute( value );
-    }
-    /// Sets the named attribute to value.
-    void SetAttribute( const char* name, bool value )			{
-        XMLAttribute* a = FindOrCreateAttribute( name );
-        a->SetAttribute( value );
-    }
-    /// Sets the named attribute to value.
-    void SetAttribute( const char* name, double value )		{
-        XMLAttribute* a = FindOrCreateAttribute( name );
-        a->SetAttribute( value );
-    }
-
-    /**
-    	Delete an attribute.
-    */
-    void DeleteAttribute( const char* name );
-
-    /// Return the first attribute in the list.
-    const XMLAttribute* FirstAttribute() const {
-        return _rootAttribute;
-    }
-    /// Query a specific attribute in the list.
-    const XMLAttribute* FindAttribute( const char* name ) const;
-
-    /** Convenience function for easy access to the text inside an element. Although easy
-    	and concise, GetText() is limited compared to getting the XMLText child
-    	and accessing it directly.
-
-    	If the first child of 'this' is a XMLText, the GetText()
-    	returns the character string of the Text node, else null is returned.
-
-    	This is a convenient method for getting the text of simple contained text:
-    	@verbatim
-    	<foo>This is text</foo>
-    		const char* str = fooElement->GetText();
-    	@endverbatim
-
-    	'str' will be a pointer to "This is text".
-
-    	Note that this function can be misleading. If the element foo was created from
-    	this XML:
-    	@verbatim
-    		<foo><b>This is text</b></foo>
-    	@endverbatim
-
-    	then the value of str would be null. The first child node isn't a text node, it is
-    	another element. From this XML:
-    	@verbatim
-    		<foo>This is <b>text</b></foo>
-    	@endverbatim
-    	GetText() will return "This is ".
-    */
-    const char* GetText() const;
-
-    /**
-    	Convenience method to query the value of a child text node. This is probably best
-    	shown by example. Given you have a document is this form:
-    	@verbatim
-    		<point>
-    			<x>1</x>
-    			<y>1.4</y>
-    		</point>
-    	@endverbatim
-
-    	The QueryIntText() and similar functions provide a safe and easier way to get to the
-    	"value" of x and y.
-
-    	@verbatim
-    		int x = 0;
-    		float y = 0;	// types of x and y are contrived for example
-    		const XMLElement* xElement = pointElement->FirstChildElement( "x" );
-    		const XMLElement* yElement = pointElement->FirstChildElement( "y" );
-    		xElement->QueryIntText( &x );
-    		yElement->QueryFloatText( &y );
-    	@endverbatim
-
-    	@returns XML_SUCCESS (0) on success, XML_CAN_NOT_CONVERT_TEXT if the text cannot be converted
-    			 to the requested type, and XML_NO_TEXT_NODE if there is no child text to query.
-
-    */
-    XMLError QueryIntText( int* ival ) const;
-    /// See QueryIntText()
-    XMLError QueryUnsignedText( unsigned* uval ) const;
-    /// See QueryIntText()
-    XMLError QueryBoolText( bool* bval ) const;
-    /// See QueryIntText()
-    XMLError QueryDoubleText( double* dval ) const;
-    /// See QueryIntText()
-    XMLError QueryFloatText( float* fval ) const;
-
-    // internal:
-    enum {
-        OPEN,		// <foo>
-        CLOSED,		// <foo/>
-        CLOSING		// </foo>
-    };
-    int ClosingType() const {
-        return _closingType;
-    }
-    char* ParseDeep( char* p, StrPair* endTag );
-    virtual XMLNode* ShallowClone( XMLDocument* document ) const;
-    virtual bool ShallowEqual( const XMLNode* compare ) const;
-
-private:
-    XMLElement( XMLDocument* doc );
-    virtual ~XMLElement();
-    XMLElement( const XMLElement& );	// not supported
-    void operator=( const XMLElement& );	// not supported
-
-    XMLAttribute* FindAttribute( const char* name );
-    XMLAttribute* FindOrCreateAttribute( const char* name );
-    //void LinkAttribute( XMLAttribute* attrib );
-    char* ParseAttributes( char* p );
-
-    int _closingType;
-    // The attribute list is ordered; there is no 'lastAttribute'
-    // because the list needs to be scanned for dupes before adding
-    // a new attribute.
-    XMLAttribute* _rootAttribute;
-};
-
-
-enum Whitespace {
-    PRESERVE_WHITESPACE,
-    COLLAPSE_WHITESPACE
-};
-
-
-/** A Document binds together all the functionality.
-	It can be saved, loaded, and printed to the screen.
-	All Nodes are connected and allocated to a Document.
-	If the Document is deleted, all its Nodes are also deleted.
-*/
-class XMLDocument : public XMLNode
-{
-    friend class XMLElement;
-public:
-    /// constructor
-    XMLDocument( bool processEntities = true, Whitespace = PRESERVE_WHITESPACE );
-    ~XMLDocument();
-
-    virtual XMLDocument* ToDocument()				{
-        return this;
-    }
-    virtual const XMLDocument* ToDocument() const	{
-        return this;
-    }
-
-    /**
-    	Parse an XML file from a character string.
-    	Returns XML_NO_ERROR (0) on success, or
-    	an errorID.
-
-    	You may optionally pass in the 'nBytes', which is
-    	the number of bytes which will be parsed. If not
-    	specified, TinyXML-2 will assume 'xml' points to a
-    	null terminated string.
-    */
-    XMLError Parse( const char* xml, size_t nBytes=(size_t)(-1) );
-
-    /**
-    	Load an XML file from disk.
-    	Returns XML_NO_ERROR (0) on success, or
-    	an errorID.
-    */
-    XMLError LoadFile( const char* filename );
-
-    /**
-    	Load an XML file from disk. You are responsible
-    	for providing and closing the FILE*.
-
-    	Returns XML_NO_ERROR (0) on success, or
-    	an errorID.
-    */
-    XMLError LoadFile( FILE* );
-
-    /**
-    	Save the XML file to disk.
-    	Returns XML_NO_ERROR (0) on success, or
-    	an errorID.
-    */
-    XMLError SaveFile( const char* filename, bool compact = false );
-
-    /**
-    	Save the XML file to disk. You are responsible
-    	for providing and closing the FILE*.
-
-    	Returns XML_NO_ERROR (0) on success, or
-    	an errorID.
-    */
-    XMLError SaveFile( FILE* fp, bool compact = false );
-
-    bool ProcessEntities() const		{
-        return _processEntities;
-    }
-    Whitespace WhitespaceMode() const	{
-        return _whitespace;
-    }
-
-    /**
-    	Returns true if this document has a leading Byte Order Mark of UTF8.
-    */
-    bool HasBOM() const {
-        return _writeBOM;
-    }
-    /** Sets whether to write the BOM when writing the file.
-    */
-    void SetBOM( bool useBOM ) {
-        _writeBOM = useBOM;
-    }
-
-    /** Return the root element of DOM. Equivalent to FirstChildElement().
-        To get the first node, use FirstChild().
-    */
-    XMLElement* RootElement()				{
-        return FirstChildElement();
-    }
-    const XMLElement* RootElement() const	{
-        return FirstChildElement();
-    }
-
-    /** Print the Document. If the Printer is not provided, it will
-        print to stdout. If you provide Printer, this can print to a file:
-    	@verbatim
-    	XMLPrinter printer( fp );
-    	doc.Print( &printer );
-    	@endverbatim
-
-    	Or you can use a printer to print to memory:
-    	@verbatim
-    	XMLPrinter printer;
-    	doc.Print( &printer );
-    	// printer.CStr() has a const char* to the XML
-    	@endverbatim
-    */
-    void Print( XMLPrinter* streamer=0 ) const;
-    virtual bool Accept( XMLVisitor* visitor ) const;
-
-    /**
-    	Create a new Element associated with
-    	this Document. The memory for the Element
-    	is managed by the Document.
-    */
-    XMLElement* NewElement( const char* name );
-    /**
-    	Create a new Comment associated with
-    	this Document. The memory for the Comment
-    	is managed by the Document.
-    */
-    XMLComment* NewComment( const char* comment );
-    /**
-    	Create a new Text associated with
-    	this Document. The memory for the Text
-    	is managed by the Document.
-    */
-    XMLText* NewText( const char* text );
-    /**
-    	Create a new Declaration associated with
-    	this Document. The memory for the object
-    	is managed by the Document.
-
-    	If the 'text' param is null, the standard
-    	declaration is used.:
-    	@verbatim
-    		<?xml version="1.0" encoding="UTF-8"?>
-    	@endverbatim
-    */
-    XMLDeclaration* NewDeclaration( const char* text=0 );
-    /**
-    	Create a new Unknown associated with
-    	this Document. The memory for the object
-    	is managed by the Document.
-    */
-    XMLUnknown* NewUnknown( const char* text );
-
-    /**
-    	Delete a node associated with this document.
-    	It will be unlinked from the DOM.
-    */
-    void DeleteNode( XMLNode* node )	{
-        node->_parent->DeleteChild( node );
-    }
-
-    void SetError( XMLError error, const char* str1, const char* str2 );
-
-    /// Return true if there was an error parsing the document.
-    bool Error() const {
-        return _errorID != XML_NO_ERROR;
-    }
-    /// Return the errorID.
-    XMLError  ErrorID() const {
-        return _errorID;
-    }
-    /// Return a possibly helpful diagnostic location or string.
-    const char* GetErrorStr1() const {
-        return _errorStr1;
-    }
-    /// Return a possibly helpful secondary diagnostic location or string.
-    const char* GetErrorStr2() const {
-        return _errorStr2;
-    }
-    /// If there is an error, print it to stdout.
-    void PrintError() const;
-    
-    /// Clear the document, resetting it to the initial state.
-    void Clear();
-
-    // internal
-    char* Identify( char* p, XMLNode** node );
-
-    virtual XMLNode* ShallowClone( XMLDocument* /*document*/ ) const	{
-        return 0;
-    }
-    virtual bool ShallowEqual( const XMLNode* /*compare*/ ) const	{
-        return false;
-    }
-
-private:
-    XMLDocument( const XMLDocument& );	// not supported
-    void operator=( const XMLDocument& );	// not supported
-
-    bool        _writeBOM;
-    bool        _processEntities;
-    XMLError    _errorID;
-    Whitespace  _whitespace;
-    const char* _errorStr1;
-    const char* _errorStr2;
-    char*       _charBuffer;
-
-    MemPoolT< sizeof(XMLElement) >	 _elementPool;
-    MemPoolT< sizeof(XMLAttribute) > _attributePool;
-    MemPoolT< sizeof(XMLText) >		 _textPool;
-    MemPoolT< sizeof(XMLComment) >	 _commentPool;
-};
-
-
-/**
-	A XMLHandle is a class that wraps a node pointer with null checks; this is
-	an incredibly useful thing. Note that XMLHandle is not part of the TinyXML-2
-	DOM structure. It is a separate utility class.
-
-	Take an example:
-	@verbatim
-	<Document>
-		<Element attributeA = "valueA">
-			<Child attributeB = "value1" />
-			<Child attributeB = "value2" />
-		</Element>
-	</Document>
-	@endverbatim
-
-	Assuming you want the value of "attributeB" in the 2nd "Child" element, it's very
-	easy to write a *lot* of code that looks like:
-
-	@verbatim
-	XMLElement* root = document.FirstChildElement( "Document" );
-	if ( root )
-	{
-		XMLElement* element = root->FirstChildElement( "Element" );
-		if ( element )
-		{
-			XMLElement* child = element->FirstChildElement( "Child" );
-			if ( child )
-			{
-				XMLElement* child2 = child->NextSiblingElement( "Child" );
-				if ( child2 )
-				{
-					// Finally do something useful.
-	@endverbatim
-
-	And that doesn't even cover "else" cases. XMLHandle addresses the verbosity
-	of such code. A XMLHandle checks for null pointers so it is perfectly safe
-	and correct to use:
-
-	@verbatim
-	XMLHandle docHandle( &document );
-	XMLElement* child2 = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).FirstChild().NextSibling().ToElement();
-	if ( child2 )
-	{
-		// do something useful
-	@endverbatim
-
-	Which is MUCH more concise and useful.
-
-	It is also safe to copy handles - internally they are nothing more than node pointers.
-	@verbatim
-	XMLHandle handleCopy = handle;
-	@endverbatim
-
-	See also XMLConstHandle, which is the same as XMLHandle, but operates on const objects.
-*/
-class XMLHandle
-{
-public:
-    /// Create a handle from any node (at any depth of the tree.) This can be a null pointer.
-    XMLHandle( XMLNode* node )												{
-        _node = node;
-    }
-    /// Create a handle from a node.
-    XMLHandle( XMLNode& node )												{
-        _node = &node;
-    }
-    /// Copy constructor
-    XMLHandle( const XMLHandle& ref )										{
-        _node = ref._node;
-    }
-    /// Assignment
-    XMLHandle& operator=( const XMLHandle& ref )							{
-        _node = ref._node;
-        return *this;
-    }
-
-    /// Get the first child of this handle.
-    XMLHandle FirstChild() 													{
-        return XMLHandle( _node ? _node->FirstChild() : 0 );
-    }
-    /// Get the first child element of this handle.
-    XMLHandle FirstChildElement( const char* value=0 )						{
-        return XMLHandle( _node ? _node->FirstChildElement( value ) : 0 );
-    }
-    /// Get the last child of this handle.
-    XMLHandle LastChild()													{
-        return XMLHandle( _node ? _node->LastChild() : 0 );
-    }
-    /// Get the last child element of this handle.
-    XMLHandle LastChildElement( const char* _value=0 )						{
-        return XMLHandle( _node ? _node->LastChildElement( _value ) : 0 );
-    }
-    /// Get the previous sibling of this handle.
-    XMLHandle PreviousSibling()												{
-        return XMLHandle( _node ? _node->PreviousSibling() : 0 );
-    }
-    /// Get the previous sibling element of this handle.
-    XMLHandle PreviousSiblingElement( const char* _value=0 )				{
-        return XMLHandle( _node ? _node->PreviousSiblingElement( _value ) : 0 );
-    }
-    /// Get the next sibling of this handle.
-    XMLHandle NextSibling()													{
-        return XMLHandle( _node ? _node->NextSibling() : 0 );
-    }
-    /// Get the next sibling element of this handle.
-    XMLHandle NextSiblingElement( const char* _value=0 )					{
-        return XMLHandle( _node ? _node->NextSiblingElement( _value ) : 0 );
-    }
-
-    /// Safe cast to XMLNode. This can return null.
-    XMLNode* ToNode()							{
-        return _node;
-    }
-    /// Safe cast to XMLElement. This can return null.
-    XMLElement* ToElement() 					{
-        return ( ( _node && _node->ToElement() ) ? _node->ToElement() : 0 );
-    }
-    /// Safe cast to XMLText. This can return null.
-    XMLText* ToText() 							{
-        return ( ( _node && _node->ToText() ) ? _node->ToText() : 0 );
-    }
-    /// Safe cast to XMLUnknown. This can return null.
-    XMLUnknown* ToUnknown() 					{
-        return ( ( _node && _node->ToUnknown() ) ? _node->ToUnknown() : 0 );
-    }
-    /// Safe cast to XMLDeclaration. This can return null.
-    XMLDeclaration* ToDeclaration() 			{
-        return ( ( _node && _node->ToDeclaration() ) ? _node->ToDeclaration() : 0 );
-    }
-
-private:
-    XMLNode* _node;
-};
-
-
-/**
-	A variant of the XMLHandle class for working with const XMLNodes and Documents. It is the
-	same in all regards, except for the 'const' qualifiers. See XMLHandle for API.
-*/
-class XMLConstHandle
-{
-public:
-    XMLConstHandle( const XMLNode* node )											{
-        _node = node;
-    }
-    XMLConstHandle( const XMLNode& node )											{
-        _node = &node;
-    }
-    XMLConstHandle( const XMLConstHandle& ref )										{
-        _node = ref._node;
-    }
-
-    XMLConstHandle& operator=( const XMLConstHandle& ref )							{
-        _node = ref._node;
-        return *this;
-    }
-
-    const XMLConstHandle FirstChild() const											{
-        return XMLConstHandle( _node ? _node->FirstChild() : 0 );
-    }
-    const XMLConstHandle FirstChildElement( const char* value=0 ) const				{
-        return XMLConstHandle( _node ? _node->FirstChildElement( value ) : 0 );
-    }
-    const XMLConstHandle LastChild()	const										{
-        return XMLConstHandle( _node ? _node->LastChild() : 0 );
-    }
-    const XMLConstHandle LastChildElement( const char* _value=0 ) const				{
-        return XMLConstHandle( _node ? _node->LastChildElement( _value ) : 0 );
-    }
-    const XMLConstHandle PreviousSibling() const									{
-        return XMLConstHandle( _node ? _node->PreviousSibling() : 0 );
-    }
-    const XMLConstHandle PreviousSiblingElement( const char* _value=0 ) const		{
-        return XMLConstHandle( _node ? _node->PreviousSiblingElement( _value ) : 0 );
-    }
-    const XMLConstHandle NextSibling() const										{
-        return XMLConstHandle( _node ? _node->NextSibling() : 0 );
-    }
-    const XMLConstHandle NextSiblingElement( const char* _value=0 ) const			{
-        return XMLConstHandle( _node ? _node->NextSiblingElement( _value ) : 0 );
-    }
-
-
-    const XMLNode* ToNode() const				{
-        return _node;
-    }
-    const XMLElement* ToElement() const			{
-        return ( ( _node && _node->ToElement() ) ? _node->ToElement() : 0 );
-    }
-    const XMLText* ToText() const				{
-        return ( ( _node && _node->ToText() ) ? _node->ToText() : 0 );
-    }
-    const XMLUnknown* ToUnknown() const			{
-        return ( ( _node && _node->ToUnknown() ) ? _node->ToUnknown() : 0 );
-    }
-    const XMLDeclaration* ToDeclaration() const	{
-        return ( ( _node && _node->ToDeclaration() ) ? _node->ToDeclaration() : 0 );
-    }
-
-private:
-    const XMLNode* _node;
-};
-
-
-/**
-	Printing functionality. The XMLPrinter gives you more
-	options than the XMLDocument::Print() method.
-
-	It can:
-	-# Print to memory.
-	-# Print to a file you provide.
-	-# Print XML without a XMLDocument.
-
-	Print to Memory
-
-	@verbatim
-	XMLPrinter printer;
-	doc.Print( &printer );
-	SomeFunction( printer.CStr() );
-	@endverbatim
-
-	Print to a File
-
-	You provide the file pointer.
-	@verbatim
-	XMLPrinter printer( fp );
-	doc.Print( &printer );
-	@endverbatim
-
-	Print without a XMLDocument
-
-	When loading, an XML parser is very useful. However, sometimes
-	when saving, it just gets in the way. The code is often set up
-	for streaming, and constructing the DOM is just overhead.
-
-	The Printer supports the streaming case. The following code
-	prints out a trivially simple XML file without ever creating
-	an XML document.
-
-	@verbatim
-	XMLPrinter printer( fp );
-	printer.OpenElement( "foo" );
-	printer.PushAttribute( "foo", "bar" );
-	printer.CloseElement();
-	@endverbatim
-*/
-class XMLPrinter : public XMLVisitor
-{
-public:
-    /** Construct the printer. If the FILE* is specified,
-    	this will print to the FILE. Else it will print
-    	to memory, and the result is available in CStr().
-    	If 'compact' is set to true, then output is created
-    	with only required whitespace and newlines.
-    */
-    XMLPrinter( FILE* file=0, bool compact = false );
-    ~XMLPrinter()	{}
-
-    /** If streaming, write the BOM and declaration. */
-    void PushHeader( bool writeBOM, bool writeDeclaration );
-    /** If streaming, start writing an element.
-        The element must be closed with CloseElement()
-    */
-    void OpenElement( const char* name );
-    /// If streaming, add an attribute to an open element.
-    void PushAttribute( const char* name, const char* value );
-    void PushAttribute( const char* name, int value );
-    void PushAttribute( const char* name, unsigned value );
-    void PushAttribute( const char* name, bool value );
-    void PushAttribute( const char* name, double value );
-    /// If streaming, close the Element.
-    void CloseElement();
-
-    /// Add a text node.
-    void PushText( const char* text, bool cdata=false );
-    /// Add a text node from an integer.
-    void PushText( int value );
-    /// Add a text node from an unsigned.
-    void PushText( unsigned value );
-    /// Add a text node from a bool.
-    void PushText( bool value );
-    /// Add a text node from a float.
-    void PushText( float value );
-    /// Add a text node from a double.
-    void PushText( double value );
-
-    /// Add a comment
-    void PushComment( const char* comment );
-
-    void PushDeclaration( const char* value );
-    void PushUnknown( const char* value );
-
-    virtual bool VisitEnter( const XMLDocument& /*doc*/ );
-    virtual bool VisitExit( const XMLDocument& /*doc*/ )			{
-        return true;
-    }
-
-    virtual bool VisitEnter( const XMLElement& element, const XMLAttribute* attribute );
-    virtual bool VisitExit( const XMLElement& element );
-
-    virtual bool Visit( const XMLText& text );
-    virtual bool Visit( const XMLComment& comment );
-    virtual bool Visit( const XMLDeclaration& declaration );
-    virtual bool Visit( const XMLUnknown& unknown );
-
-    /**
-    	If in print to memory mode, return a pointer to
-    	the XML file in memory.
-    */
-    const char* CStr() const {
-        return _buffer.Mem();
-    }
-    /**
-    	If in print to memory mode, return the size
-    	of the XML file in memory. (Note the size returned
-    	includes the terminating null.)
-    */
-    int CStrSize() const {
-        return _buffer.Size();
-    }
-
-private:
-    void SealElement();
-    void PrintSpace( int depth );
-    void PrintString( const char*, bool restrictedEntitySet );	// prints out, after detecting entities.
-    void Print( const char* format, ... );
-
-    bool _elementJustOpened;
-    bool _firstElement;
-    FILE* _fp;
-    int _depth;
-    int _textDepth;
-    bool _processEntities;
-    bool _compactMode;
-
-    enum {
-        ENTITY_RANGE = 64,
-        BUF_SIZE = 200
-    };
-    bool _entityFlag[ENTITY_RANGE];
-    bool _restrictedEntityFlag[ENTITY_RANGE];
-
-    DynArray< const char*, 10 > _stack;
-    DynArray< char, 20 > _buffer;
-#ifdef _MSC_VER
-    DynArray< char, 20 > _accumulator;
-#endif
-};
-
-
-}	// tinyxml2
-
-
-#endif // TINYXML2_INCLUDED

+ 17 - 2
engine/compilers/lua/LuaCompiler.cpp

@@ -24,6 +24,7 @@ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 OTHER DEALINGS IN THE SOFTWARE.
 */
 
+#include "Config.h"
 #include "LuaCompiler.h"
 #include "LuaResource.h"
 #include "TempAllocator.h"
@@ -34,6 +35,20 @@ OTHER DEALINGS IN THE SOFTWARE.
 namespace crown
 {
 
+#ifdef WINDOWS
+	#define LUAJIT_EXECUTABLE "luajit.exe"
+#else
+	#define LUAJIT_EXECUTABLE "./luajit"
+#endif
+
+#if defined(CROWN_DEBUG) || defined(CROWN_DEVELOPMENT)
+	#define LUAJIT_FLAGS "-bg" // Keep debug info
+#else
+	#define LUAJIT_FLAGS "-b"
+#endif
+
+
+
 //-----------------------------------------------------------------------------
 LuaCompiler::LuaCompiler()
 	: m_luajit_blob_size(0), m_luajit_blob(NULL)
@@ -57,8 +72,8 @@ size_t LuaCompiler::compile_impl(Filesystem& fs, const char* resource_path)
 
 	const char* luajit[] =
 	{
-		"./luajit",
-		"-b",
+		LUAJIT_EXECUTABLE,
+		LUAJIT_FLAGS,
 		res_abs_path.c_str(),
 		bc_abs_path.c_str(),
 		NULL

+ 199 - 0
engine/compilers/mesh/MeshCompiler.cpp

@@ -0,0 +1,199 @@
+/*
+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 "MeshCompiler.h"
+#include "DynamicString.h"
+#include "TempAllocator.h"
+#include "Filesystem.h"
+#include "JSONParser.h"
+#include "Log.h"
+
+namespace crown
+{
+
+//-----------------------------------------------------------------------------
+MeshCompiler::MeshCompiler()
+	: m_vertices(default_allocator()), m_indices(default_allocator())
+{
+}
+
+//-----------------------------------------------------------------------------
+MeshCompiler::~MeshCompiler()
+{
+}
+
+//-----------------------------------------------------------------------------
+size_t MeshCompiler::compile_impl(Filesystem& fs, const char* resource_path)
+{
+	File* file = fs.open(resource_path, FOM_READ);
+	char* buf = (char*)default_allocator().allocate(file->size());
+	file->read(buf, file->size());
+
+	JSONParser json(buf);
+	JSONElement root = json.root();
+
+	// Read data arrays
+	JSONElement position = root.key_or_nil("position");
+	JSONElement normal = root.key_or_nil("normal");
+	JSONElement texcoord = root.key_or_nil("texcoord");
+
+	m_has_normal = false;
+	m_has_texcoord = false;
+
+	if (position.is_nil())
+	{
+		Log::e("Bad mesh: array 'position' not found.");
+		return 0;
+	}
+	List<float> position_array(default_allocator());
+	position.array_value(position_array);
+
+
+	List<float> normal_array(default_allocator());
+	if (!normal.is_nil())
+	{
+		m_has_normal = true;
+		normal.array_value(normal_array);
+	}
+
+	List<float> texcoord_array(default_allocator());
+	if (!texcoord.is_nil())
+	{
+		m_has_texcoord = true;
+		texcoord.array_value(texcoord_array);
+	}
+
+	// Read index arrays
+	JSONElement index = root.key_or_nil("index");
+	if (index.is_nil())
+	{
+		Log::e("Bad mesh: array 'index' not found.");
+		return 0;
+	}
+
+	List<uint16_t> position_index(default_allocator());
+	List<uint16_t> normal_index(default_allocator());
+	List<uint16_t> texcoord_index(default_allocator());
+
+	index[0].array_value(position_index);
+
+	if (m_has_normal)
+	{
+		index[1].array_value(normal_index);
+	}
+
+	if (m_has_texcoord)
+	{
+		index[2].array_value(texcoord_index);
+	}
+
+	// Generate vb/ib
+	uint32_t idx = 0;
+	for (uint32_t i = 0; i < position_index.size(); i++)
+	{
+		MeshVertex v;
+
+		uint16_t p_idx = position_index[i] * 3;
+		v.position = Vec3(position_array[p_idx], position_array[p_idx + 1], position_array[p_idx + 2]);
+
+		if (m_has_normal)
+		{
+			uint16_t n_idx = normal_index[i] * 3;
+			v.normal = Vec3(normal_array[n_idx], normal_array[n_idx + 1], normal_array[n_idx + 2]);
+		}
+
+		if (m_has_texcoord)
+		{
+			uint16_t t_idx = texcoord_index[i] * 2;
+			v.texcoord = Vec2(texcoord_array[t_idx], texcoord_array[t_idx + 1]);
+		}
+
+
+		uint32_t f_idx = 0;
+		bool found = false;
+		for (; f_idx < m_vertices.size(); f_idx++)
+		{
+			if (m_vertices[f_idx] == v)
+			{
+				found = true;
+				break;
+			}
+		}
+
+		if (found)
+		{
+			m_indices.push_back(f_idx);
+		}
+		else
+		{
+			m_vertices.push_back(v);
+			m_indices.push_back(idx);
+			idx++;
+		}
+	}
+
+	m_mesh_header.version = MESH_VERSION;
+	m_mesh_header.num_meshes = 1;
+	m_mesh_header.num_joints = 0;
+	//m_mesh_header.padding[0] = 0xCECECECE;
+
+	default_allocator().deallocate(buf);
+	fs.close(file);
+
+	return sizeof(MeshHeader) + sizeof(MeshData) +
+	 		m_vertices.size() * sizeof(MeshVertex) +
+	 		m_indices.size() * sizeof(uint16_t);
+}
+
+//-----------------------------------------------------------------------------
+void MeshCompiler::write_impl(File* out_file)
+{
+	MeshData data;
+	data.vertices.num_vertices = m_vertices.size();
+	data.vertices.format = VERTEX_P3_N3_T2;
+	data.vertices.offset = sizeof(MeshHeader) + sizeof(MeshData);
+
+	data.indices.num_indices = m_indices.size();
+	data.indices.offset = sizeof(MeshHeader) + sizeof(MeshData) + m_vertices.size() * sizeof(MeshVertex);
+
+	// Write header
+	out_file->write((char*)&m_mesh_header, sizeof(MeshHeader));
+
+	// Write mesh metadata
+	out_file->write((char*)&data, sizeof(MeshData));
+
+	// Write vertices
+	out_file->write((char*) m_vertices.begin(), m_vertices.size() * sizeof(MeshVertex));
+
+	// Write indices
+	out_file->write((char*) m_indices.begin(), m_indices.size() * sizeof(uint16_t));
+
+	// Cleanup
+	m_vertices.clear();
+	m_indices.clear();
+}
+
+} // namespace crown

+ 38 - 4
engine/renderers/IndexBuffer.h → engine/compilers/mesh/MeshCompiler.h

@@ -26,13 +26,47 @@ OTHER DEALINGS IN THE SOFTWARE.
 
 #pragma once
 
-#include "Types.h"
+#include "Compiler.h"
+#include "MeshResource.h"
+#include "Vec3.h"
+#include "Vec2.h"
+#include "List.h"
 
 namespace crown
 {
 
-// Max number of index buffers a renderer can hold.
-const uint32_t MAX_INDEX_BUFFERS = 4096;
+struct MeshVertex
+{
+	Vec3 position;
+	Vec3 normal;
+	Vec2 texcoord;
 
-} // namespace crown
+	bool operator==(const MeshVertex& other)
+	{
+		return position == other.position &&
+				normal == other.normal &&
+				texcoord == other.texcoord;
+	}
+};
+
+class MeshCompiler : public Compiler
+{
+public:
+
+						MeshCompiler();
+						~MeshCompiler();
 
+	size_t				compile_impl(Filesystem& fs, const char* resource_path);
+	void				write_impl(File* out_file);
+
+private:
+
+	MeshHeader			m_mesh_header;
+	bool				m_has_normal;
+	bool				m_has_texcoord;
+
+	List<MeshVertex>	m_vertices;
+	List<uint16_t>		m_indices;
+};
+
+} // namespace crown

+ 139 - 0
engine/compilers/package/PackageCompiler.cpp

@@ -0,0 +1,139 @@
+/*
+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 "Allocator.h"
+#include "File.h"
+#include "Filesystem.h"
+#include "Hash.h"
+#include "JSONParser.h"
+#include "PackageCompiler.h"
+#include "PackageResource.h"
+#include "TempAllocator.h"
+
+namespace crown
+{
+
+//-----------------------------------------------------------------------------
+PackageCompiler::PackageCompiler()
+	: m_has_texture(false), m_has_lua(false), m_textures(default_allocator()), m_scripts(default_allocator())
+{
+}
+
+//-----------------------------------------------------------------------------
+size_t PackageCompiler::compile_impl(Filesystem& fs, const char* resource_path)
+{
+	File* file = fs.open(resource_path, FOM_READ);
+
+	char file_buf[4096];
+	file->read(file_buf, file->size());
+	fs.close(file);
+
+	JSONParser json(file_buf);
+	JSONElement root = json.root();
+
+	// Check for resource types
+	if (root.has_key("texture"))
+	{
+		JSONElement texture_array = root.key("texture");
+		uint32_t texture_array_size = texture_array.size();
+
+		for (uint32_t i = 0; i < texture_array_size; i++)
+		{
+			TempAllocator256 alloc;
+			DynamicString texture_name(alloc);
+			texture_name += texture_array[i].string_value();
+			texture_name += ".texture";
+
+			if (!fs.is_file(texture_name.c_str()))
+			{
+				Log::e("Texture '%s' does not exist.", texture_name.c_str());
+				return 0;
+			}
+
+			ResourceId id;
+			id.id = hash::murmur2_64(texture_name.c_str(), string::strlen(texture_name.c_str()), 0);
+			m_textures.push_back(id);
+		}
+	}
+
+	// Check for scripts
+	if (root.has_key("lua"))
+	{
+		JSONElement lua_array = root.key("lua");
+		//lua_array = root.key("lua");
+		uint32_t lua_array_size = lua_array.size();
+
+		for (uint32_t i = 0; i < lua_array_size; i++)
+		{
+			TempAllocator256 alloc;
+			DynamicString lua_name(alloc);
+			lua_name += lua_array[i].string_value();
+			lua_name += ".lua";
+
+			if (!fs.is_file(lua_name.c_str()))
+			{
+				Log::e("Lua script '%s' does not exist.", lua_name.c_str());
+				return 0;
+			}
+
+			ResourceId id;
+			id.id = hash::murmur2_64(lua_name.c_str(), string::strlen(lua_name.c_str()), 0);
+			m_scripts.push_back(id);
+		}
+	}
+
+	return sizeof(PackageHeader) +
+			m_textures.size() * sizeof(ResourceId) +
+			m_scripts.size() * sizeof(ResourceId);
+}
+
+//-----------------------------------------------------------------------------
+void PackageCompiler::write_impl(File* out_file)
+{
+	PackageHeader header;
+	header.num_textures = m_textures.size();
+	header.num_scripts = m_scripts.size();
+
+	header.textures_offset = sizeof(PackageHeader);
+	header.scripts_offset  = header.textures_offset + sizeof(ResourceId) * header.num_textures;
+
+	out_file->write((char*) &header, sizeof(PackageHeader));
+
+	if (m_textures.size() > 0)
+	{
+		out_file->write((char*) m_textures.begin(), sizeof(ResourceId) * header.num_textures);		
+	}
+	if (m_scripts.size() > 0)
+	{
+		out_file->write((char*) m_scripts.begin(), sizeof(ResourceId) * header.num_scripts);
+	}
+
+	// Cleanup
+	m_textures.clear();
+	m_scripts.clear();
+}
+
+} // namespace crown

+ 18 - 10
engine/renderers/VertexBuffer.h → engine/compilers/package/PackageCompiler.h

@@ -26,21 +26,29 @@ OTHER DEALINGS IN THE SOFTWARE.
 
 #pragma once
 
-#include "Types.h"
+#include "Compiler.h"
+#include "Resource.h"
+#include "List.h"
 
 namespace crown
 {
 
-// Max number of vertex buffers a renderer can hold.
-const uint32_t MAX_VERTEX_BUFFERS = 4096;
-
-enum VertexBufferMode
+class PackageCompiler : public Compiler
 {
-	VBM_VERTEX_ONLY		= 0,
-	VBM_TEXTURE_COORDS	= 1,
-	VBM_NORMAL_COORDS	= 2,
-	VBM_COLOR_COORDS	= 4
+public:
+
+	PackageCompiler();
+
+	size_t compile_impl(Filesystem& fs, const char* resource_path);
+	void write_impl(File* out_file);
+
+private:
+
+	bool m_has_texture;
+	bool m_has_lua;
+
+	List<ResourceId> m_textures;
+	List<ResourceId> m_scripts;
 };
 
 } // namespace crown
-

+ 2 - 2
engine/compilers/texture/TextureCompiler.cpp

@@ -76,7 +76,7 @@ size_t TextureCompiler::compile_impl(Filesystem& fs, const char* resource_path)
 		case 2:
 		case 3:
 		{
-			m_texture_header.format = PF_RGB_8;
+			m_texture_header.format = PIXEL_RGB_8;
 
 			m_texture_data_size = m_tga_size * 3;
 			m_texture_data = (uint8_t*)default_allocator().allocate(m_texture_data_size);
@@ -85,7 +85,7 @@ size_t TextureCompiler::compile_impl(Filesystem& fs, const char* resource_path)
 		}
 		case 4:
 		{
-			m_texture_header.format = PF_RGBA_8;
+			m_texture_header.format = PIXEL_RGBA_8;
 
 			m_texture_data_size = m_tga_size * m_tga_channels;
 			m_texture_data = (uint8_t*)default_allocator().allocate(m_texture_data_size);

+ 26 - 42
engine/core/containers/IdTable.h

@@ -33,25 +33,22 @@ OTHER DEALINGS IN THE SOFTWARE.
 namespace crown
 {
 
+#define INVALID_ID 65535
+
 struct Id
 {
-	union
-	{
-		uint16_t id;
-		uint16_t next;
-	};
-
+	uint16_t id;
 	uint16_t index;
 };
 
 /// Table of Ids.
+template <uint32_t MAX_NUM_ID>
 class IdTable
 {
 public:
 
-	/// Creates the table for tracking exactly @a max_ids - 1 unique Ids.
-					IdTable(Allocator& allocator, uint16_t max_ids);
-					~IdTable();
+	/// Creates the table for tracking exactly @a MAX_NUM_ID - 1 unique Ids.
+					IdTable();
 
 	/// Returns a new Id.
 	Id				create();
@@ -69,13 +66,6 @@ private:
 
 private:
 
-	Allocator&		m_allocator;
-
-	// The maximum number of Ids the table can track.
-	// The last valid id is reserved and cannot be used to
-	// refer to Ids from the outside.
-	const uint16_t	m_max_ids;
-
 	// The index of the first unused id.
 	uint16_t		m_freelist;
 
@@ -86,41 +76,31 @@ private:
 	uint16_t		m_next_id;
 
 	// Table of ids.
-	Id*				m_ids;
+	// The last valid id is reserved and cannot be used to
+	// refer to Ids from the outside.
+	Id				m_ids[MAX_NUM_ID];
 };
 
 //-----------------------------------------------------------------------------
-inline IdTable::IdTable(Allocator& allocator, uint16_t max_ids) :
-	m_allocator(allocator),
-	m_max_ids(max_ids),
-	m_freelist(max_ids),
-	m_last_index(0),
-	m_next_id(0)
+template <uint32_t MAX_NUM_ID>
+inline IdTable<MAX_NUM_ID>::IdTable()
+	: m_freelist(MAX_NUM_ID), m_last_index(0), m_next_id(0)
 {
-	m_ids = (Id*)m_allocator.allocate(m_max_ids * sizeof(Id));
-}
-
-//-----------------------------------------------------------------------------
-inline IdTable::~IdTable()
-{
-	if (m_ids)
-	{
-		m_allocator.deallocate(m_ids);
-	}
 }
 
 //-----------------------------------------------------------------------------
-inline Id IdTable::create()
+template <uint32_t MAX_NUM_ID>
+inline Id IdTable<MAX_NUM_ID>::create()
 {
 	// Obtain a new id
 	Id id;
 	id.id = next_id();
 
 	// Recycle slot if there are any
-	if (m_freelist != m_max_ids)
+	if (m_freelist != MAX_NUM_ID)
 	{
 		id.index = m_freelist;
-		m_freelist = m_ids[m_freelist].next;
+		m_freelist = m_ids[m_freelist].id;
 	}
 	else
 	{
@@ -133,24 +113,28 @@ inline Id IdTable::create()
 }
 
 //-----------------------------------------------------------------------------
-inline void IdTable::destroy(Id id)
+template <uint32_t MAX_NUM_ID>
+inline void IdTable<MAX_NUM_ID>::destroy(Id id)
 {
 	CE_ASSERT(has(id), "IdTable does not have ID: %d,%d", id.id, id.index);
 
-	m_ids[id.index].next = m_freelist;
+	m_ids[id.index].id = INVALID_ID;
+	m_ids[id.index].index = m_freelist;
 	m_freelist = id.index;
 }
 
 //-----------------------------------------------------------------------------
-inline bool IdTable::has(Id id) const
+template <uint32_t MAX_NUM_ID>
+inline bool IdTable<MAX_NUM_ID>::has(Id id) const
 {
-	return id.index < m_max_ids && m_ids[id.index].id == id.id;
+	return id.index < MAX_NUM_ID && m_ids[id.index].id == id.id;
 }
 
 //-----------------------------------------------------------------------------
-inline uint16_t IdTable::next_id()
+template <uint32_t MAX_NUM_ID>
+inline uint16_t IdTable<MAX_NUM_ID>::next_id()
 {
-	CE_ASSERT(m_next_id < m_max_ids, "Maximum number of IDs reached");
+	CE_ASSERT(m_next_id < MAX_NUM_ID, "Maximum number of IDs reached");
 
 	return m_next_id++;
 }

+ 222 - 18
engine/core/json/JSONParser.cpp

@@ -192,28 +192,42 @@ static bool is_escapee(char c)
 }
 
 //--------------------------------------------------------------------------
-JSONElement::JSONElement() :
-	m_parser(NULL),
-	m_at(NULL),
-	m_begin(NULL)
+JSONElement::JSONElement()
+	: m_parser(NULL), m_begin(NULL), m_at(NULL)
 {
 }
 
 //--------------------------------------------------------------------------
-JSONElement::JSONElement(JSONParser& parser, const char* at) :
-	m_parser(&parser),
-	m_at(at),
-	m_begin(at)
+JSONElement::JSONElement(JSONParser& parser, const char* at)
+	: m_parser(&parser), m_begin(at), m_at(at)
 {
 }
 
+//--------------------------------------------------------------------------
+JSONElement::JSONElement(const JSONElement& other)
+	: m_parser(other.m_parser), m_begin(other.m_at), m_at(other.m_at)
+{
+}
+
+//--------------------------------------------------------------------------
+JSONElement& JSONElement::operator=(const JSONElement& other)
+{
+	m_parser = other.m_parser;
+
+	// Our begin is the other's at
+	m_begin = other.m_at;
+	m_at = other.m_at;
+
+	return *this;
+}
+
 //--------------------------------------------------------------------------
 JSONElement& JSONElement::operator[](uint32_t i)
 {
 	TempAllocator1024 alloc;
 	List<const char*> array(alloc);
 
-	JSONParser::parse_array(m_at, array);
+	JSONParser::parse_array(m_begin, array);
 
 	CE_ASSERT(i < array.size(), "Index out of bounds");
 
@@ -228,13 +242,35 @@ JSONElement& JSONElement::index(uint32_t i)
 	return this->operator[](i);
 }
 
+//--------------------------------------------------------------------------
+JSONElement JSONElement::index_or_nil(uint32_t i)
+{
+	if (m_at != NULL)
+	{
+		TempAllocator1024 alloc;
+		List<const char*> array(alloc);
+
+		JSONParser::parse_array(m_begin, array);
+
+		if (i >= array.size())
+		{
+			return JSONElement();
+		}
+
+		m_at = array[i];
+		return *this;
+	}
+
+	return JSONElement();
+}
+
 //--------------------------------------------------------------------------
 JSONElement& JSONElement::key(const char* k)
 {
 	TempAllocator1024 alloc;
 	List<JSONPair> object(alloc);
 
-	JSONParser::parse_object(m_at, object);
+	JSONParser::parse_object(m_begin, object);
 
 	bool found = false;
 
@@ -257,12 +293,49 @@ JSONElement& JSONElement::key(const char* k)
 	return *this;
 }
 
+//--------------------------------------------------------------------------
+JSONElement JSONElement::key_or_nil(const char* k)
+{
+	if (m_at != NULL)
+	{
+		TempAllocator1024 alloc;
+		List<JSONPair> object(alloc);
+
+		JSONParser::parse_object(m_begin, object);
+
+		bool found = false;
+
+		for (uint32_t i = 0; i < object.size(); i++)
+		{
+			TempAllocator256 key_alloc;
+			List<char> key(key_alloc);
+
+			JSONParser::parse_string(object[i].key, key);
+
+			if (string::strcmp(k, key.begin()) == 0)
+			{
+				m_at = object[i].val;
+				found = true;
+			}
+		}
+
+		if (!found)
+		{
+			return JSONElement();
+		}
+
+		return *this;
+	}
+
+	return JSONElement();
+}
+
 //--------------------------------------------------------------------------
 bool JSONElement::has_key(const char* k) const
 {
 	TempAllocator1024 alloc;
 	List<JSONPair> object(alloc);
-	JSONParser::parse_object(m_at, object);
+	JSONParser::parse_object(m_begin, object);
 
 	for (uint32_t i = 0; i < object.size(); i++)
 	{
@@ -285,7 +358,7 @@ bool JSONElement::is_key_unique(const char* k) const
 {
 	TempAllocator1024 alloc;
 	List<JSONPair> object(alloc);
-	JSONParser::parse_object(m_at, object);
+	JSONParser::parse_object(m_begin, object);
 
 	bool found = false;
 
@@ -355,45 +428,176 @@ const char* JSONElement::string_value()
 	return string.begin();
 }
 
+//--------------------------------------------------------------------------
+void JSONElement::array_value(List<bool>& array)
+{
+	TempAllocator1024 alloc;
+	List<const char*> temp(alloc);
+
+	JSONParser::parse_array(m_at, temp);
+
+	for (uint32_t i = 0; i < temp.size(); i++)
+	{
+		array.push_back(JSONParser::parse_bool(temp[i]));
+	}
+
+	m_at = m_begin;
+}
+
+//--------------------------------------------------------------------------
+void JSONElement::array_value(List<int16_t>& array)
+{
+	TempAllocator1024 alloc;
+	List<const char*> temp(alloc);
+
+	JSONParser::parse_array(m_at, temp);
+
+	for (uint32_t i = 0; i < temp.size(); i++)
+	{
+		array.push_back((int16_t)JSONParser::parse_int(temp[i]));
+	}
+
+	m_at = m_begin;
+}
+
+//--------------------------------------------------------------------------
+void JSONElement::array_value(List<uint16_t>& array)
+{
+	TempAllocator1024 alloc;
+	List<const char*> temp(alloc);
+
+	JSONParser::parse_array(m_at, temp);
+
+	for (uint32_t i = 0; i < temp.size(); i++)
+	{
+		array.push_back((uint16_t)JSONParser::parse_int(temp[i]));
+	}
+
+	m_at = m_begin;
+}
+
+//--------------------------------------------------------------------------
+void JSONElement::array_value(List<int32_t>& array)
+{
+	TempAllocator1024 alloc;
+	List<const char*> temp(alloc);
+
+	JSONParser::parse_array(m_at, temp);
+
+	for (uint32_t i = 0; i < temp.size(); i++)
+	{
+		array.push_back((int32_t)JSONParser::parse_int(temp[i]));
+	}
+
+	m_at = m_begin;
+}
+
+//--------------------------------------------------------------------------
+void JSONElement::array_value(List<uint32_t>& array)
+{
+	TempAllocator1024 alloc;
+	List<const char*> temp(alloc);
+
+	JSONParser::parse_array(m_at, temp);
+
+	for (uint32_t i = 0; i < temp.size(); i++)
+	{
+		array.push_back((uint32_t)JSONParser::parse_int(temp[i]));
+	}
+
+	m_at = m_begin;
+}
+
+//--------------------------------------------------------------------------
+void JSONElement::array_value(List<float>& array)
+{
+	TempAllocator1024 alloc;
+	List<const char*> temp(alloc);
+
+	JSONParser::parse_array(m_at, temp);
+
+	for (uint32_t i = 0; i < temp.size(); i++)
+	{
+		array.push_back(JSONParser::parse_float(temp[i]));
+	}
+
+	m_at = m_begin;
+}
+
 //--------------------------------------------------------------------------
 bool JSONElement::is_nil() const
 {
-	return JSONParser::type(m_at) == JT_NIL;
+	if (m_at != NULL)
+	{
+		return JSONParser::type(m_at) == JT_NIL;
+	}
+
+	return true;
 }
 
 //--------------------------------------------------------------------------
 bool JSONElement::is_bool() const
 {
-	return JSONParser::type(m_at) == JT_BOOL;
+	if (m_at != NULL)
+	{
+		return JSONParser::type(m_at) == JT_BOOL;
+	}
+
+	return false;
 }
 
 //--------------------------------------------------------------------------
 bool JSONElement::is_number() const
 {
-	return JSONParser::type(m_at) == JT_NUMBER;
+	if (m_at != NULL)
+	{
+		return JSONParser::type(m_at) == JT_NUMBER;		
+	}
+
+	return false;
 }
 
 //--------------------------------------------------------------------------
 bool JSONElement::is_string() const
 {
-	return JSONParser::type(m_at) == JT_STRING;
+	if (m_at != NULL)
+	{
+		return JSONParser::type(m_at) == JT_STRING;
+	}
+
+	return false;
 }
 
 //--------------------------------------------------------------------------
 bool JSONElement::is_array() const
 {
-	return JSONParser::type(m_at) == JT_ARRAY;
+	if (m_at != NULL)
+	{
+		return JSONParser::type(m_at) == JT_ARRAY;
+	}
+
+	return false;
 }
 
 //--------------------------------------------------------------------------
 bool JSONElement::is_object() const
 {
-	return JSONParser::type(m_at) == JT_OBJECT;
+	if (m_at != NULL)
+	{
+		return JSONParser::type(m_at) == JT_OBJECT;
+	}
+
+	return false;
 }
 
 //--------------------------------------------------------------------------
 uint32_t JSONElement::size() const
 {
+	if (m_at == NULL)
+	{
+		return 0;
+	}
+
 	switch(JSONParser::type(m_at))
 	{
 		case JT_NIL:

+ 40 - 7
engine/core/json/JSONParser.h

@@ -58,18 +58,24 @@ class JSONElement
 {
 public:
 
-	/// Used only to forward-instantiate elements.
-	/// In order to be able to use the element, it must be
-	/// obtained from JSONParser::root() or copied from an
-	/// already existent and valid element.
+	/// Construct the nil JSONElement.
+	/// Used to forward-instantiate elements or as a special
+	/// nil element.
 						JSONElement();
+						JSONElement(const JSONElement& other);
+
+	JSONElement&		operator=(const JSONElement& other);
 
 	/// Returns the @a i -th item of the current array.
 	JSONElement&		operator[](uint32_t i);
 
-	/// @copydoc JSONParser::operator[]
+	/// @copydoc JSONElement::operator[]
 	JSONElement&		index(uint32_t i);
 
+	/// Returns the @a i -th item of the current array or
+	/// the special nil JSONElement() if the index does not exist.
+	JSONElement			index_or_nil(uint32_t i);
+
 	/// Returns the element corresponding to key @a k of the
 	/// current object.
 	/// @note
@@ -77,6 +83,10 @@ public:
 	/// key in order of appearance will be selected.
 	JSONElement&		key(const char* k);
 
+	/// Returns the element corresponding to key @a k of the current
+	/// object, or the special nil JSONElement() if the key does not exist.
+	JSONElement			key_or_nil(const char* k);
+
 	/// Returns whether the element has the @a k key.
 	bool				has_key(const char* k) const;
 
@@ -126,13 +136,36 @@ public:
 	/// instead of copying its content somewhere else.
 	const char*			string_value();
 
+	/// Returns the array value of the element.
+	/// @note
+	/// Calling this function is way faster than accessing individual
+	/// array elements by JSONElement::operator[] and it is the very preferred way
+	/// for retrieving array elemets. However, you have to be sure that the array
+	/// contains only items of the given @array type.
+	void				array_value(List<bool>& array);
+
+	/// @copydoc JSONElement::array_value(List<bool>&)
+	void				array_value(List<int16_t>& array);
+
+	/// @copydoc JSONElement::array_value(List<bool>&)
+	void				array_value(List<uint16_t>& array);
+
+	/// @copydoc JSONElement::array_value(List<bool>&)
+	void				array_value(List<int32_t>& array);
+
+	/// @copydoc JSONElement::array_value(List<bool>&)
+	void				array_value(List<uint32_t>& array);
+
+	/// @copydoc JSONElement::array_value(List<bool>&)
+	void				array_value(List<float>& array);
+
 private:
 
-						JSONElement(JSONParser& parser, const char* at);
+	explicit			JSONElement(JSONParser& parser, const char* at);
 
 	JSONParser*			m_parser;
-	const char*			m_at;
 	const char*			m_begin;
+	const char*			m_at;
 
 	friend class 		JSONParser;
 };

+ 0 - 38
engine/core/mem/Allocator.cpp

@@ -1,38 +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 "HeapAllocator.h"
-
-namespace crown
-{
-
-HeapAllocator g_default_allocator;
-Allocator& default_allocator()
-{
-	return g_default_allocator;
-}
-
-} // namespace crown

+ 15 - 5
engine/core/mem/LinearAllocator.cpp

@@ -30,17 +30,27 @@ namespace crown
 {
 
 //-----------------------------------------------------------------------------
-LinearAllocator::LinearAllocator(void* start, size_t size) :
-	m_physical_start(start),
-	m_total_size(size),
-	m_offset(0)
+LinearAllocator::LinearAllocator(Allocator& backing, size_t size)
+	: m_backing(&backing), m_physical_start(NULL), m_total_size(size), m_offset(0)
+{
+	m_physical_start = backing.allocate(size);
+}
+
+//-----------------------------------------------------------------------------
+LinearAllocator::LinearAllocator(void* start, size_t size)
+	: m_backing(NULL), m_physical_start(start), m_total_size(size), m_offset(0)
 {
 }
 
 //-----------------------------------------------------------------------------
 LinearAllocator::~LinearAllocator()
 {
-	CE_ASSERT(m_offset == 0, "Memory leak of %d bytes", m_offset);
+	if (m_backing)
+	{
+		m_backing->deallocate(m_physical_start);
+	}
+
+	CE_ASSERT(m_offset == 0, "Memory leak of %d bytes, maybe you forgot to call clear()?", m_offset);
 }
 
 //-----------------------------------------------------------------------------

+ 2 - 0
engine/core/mem/LinearAllocator.h

@@ -37,6 +37,7 @@ class LinearAllocator : public Allocator
 {
 public:
 
+				LinearAllocator(Allocator& backing, size_t size);
 				LinearAllocator(void* start, size_t size);
 				~LinearAllocator();
 
@@ -58,6 +59,7 @@ public:
 
 private:
 
+	Allocator*	m_backing;
 	void*		m_physical_start;
 	size_t		m_total_size;
 	size_t		m_offset;

+ 43 - 16
engine/core/mem/Memory.cpp

@@ -27,30 +27,57 @@ OTHER DEALINGS IN THE SOFTWARE.
 #include "Memory.h"
 #include "HeapAllocator.h"
 
-//-----------------------------------------------------------------------------
-void* operator new(size_t) throw (std::bad_alloc)
-{
-	CE_ASSERT(false, "operator new forbidden");
+// //-----------------------------------------------------------------------------
+// void* operator new(size_t) throw (std::bad_alloc)
+// {
+// 	CE_ASSERT(false, "operator new forbidden");
 
-	return NULL;
-}
+// 	return NULL;
+// }
+
+// //-----------------------------------------------------------------------------
+// void* operator new[](size_t) throw (std::bad_alloc)
+// {
+// 	CE_ASSERT(false, "operator new[] forbidden");
+
+// 	return NULL;
+// }
+
+// //-----------------------------------------------------------------------------
+// void operator delete(void*) throw ()
+// {
+// 	CE_ASSERT(false, "operator delete forbidden");
+// }
+
+// //-----------------------------------------------------------------------------
+// void operator delete[](void*) throw ()
+// {
+// 	CE_ASSERT(false, "operator delete[] forbidden");
+// }
 
-//-----------------------------------------------------------------------------
-void* operator new[](size_t) throw (std::bad_alloc)
+namespace crown
 {
-	CE_ASSERT(false, "operator new[] forbidden");
+namespace memory
+{
+
+static char buffer[1024];
+static HeapAllocator* g_default_allocator = NULL;
 
-	return NULL;
+void init()
+{
+	g_default_allocator = new (buffer) HeapAllocator();
 }
 
-//-----------------------------------------------------------------------------
-void operator delete(void*) throw ()
+void shutdown()
 {
-	CE_ASSERT(false, "operator delete forbidden");
+	g_default_allocator->~HeapAllocator();
 }
 
-//-----------------------------------------------------------------------------
-void operator delete[](void*) throw ()
+} // namespace memory
+
+Allocator& default_allocator()
 {
-	CE_ASSERT(false, "operator delete[] forbidden");
+	return *memory::g_default_allocator;
 }
+
+} // namespace crown

+ 10 - 0
engine/core/mem/Memory.h

@@ -37,6 +37,16 @@ namespace memory
 const uint32_t	PADDING_VALUE	= 0xFFFFFFFFu;	//!< Value used to fill unused memory
 const size_t	DEFAULT_ALIGN	= 4;			//!< Default memory alignment in bytes
 
+/// Constructs the initial default allocators.
+/// @note
+/// Has to be called before anything else during the engine startup.
+void init();
+
+/// Destroys the allocators created with memory::init().
+/// @note
+/// Should be the last call of the program.
+void shutdown();
+
 /// Returns the pointer @a p aligned to the desired @a align byte
 inline void* align_top(void* p, size_t align)
 {

+ 1 - 0
engine/core/strings/StringStream.h

@@ -29,6 +29,7 @@ OTHER DEALINGS IN THE SOFTWARE.
 #include <stdio.h>
 #include "List.h"
 #include "StringUtils.h"
+#include "OS.h"
 
 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;

+ 29 - 4
engine/lua/LuaDevice.cpp

@@ -25,6 +25,7 @@ OTHER DEALINGS IN THE SOFTWARE.
 */
 
 #include "Device.h"
+#include "ResourcePackage.h"
 #include "LuaEnvironment.h"
 #include "LuaStack.h"
 
@@ -71,13 +72,37 @@ CE_EXPORT int device_stop(lua_State* /*L*/)
 	return 0;
 }
 
+//-----------------------------------------------------------------------------
+CE_EXPORT int device_create_resource_package(lua_State* L)
+{
+	LuaStack stack(L);
+
+	const char* package = stack.get_string(1);
+	stack.push_lightdata(device()->create_resource_package(package));
+
+	return 1;
+}
+
+//-----------------------------------------------------------------------------
+CE_EXPORT int device_destroy_resource_package(lua_State* L)
+{
+	LuaStack stack(L);
+
+	ResourcePackage* package = (ResourcePackage*) stack.get_lightdata(1);
+	device()->destroy_resource_package(package);
+
+	return 0;
+}
+
 //-----------------------------------------------------------------------------
 void load_device(LuaEnvironment& env)
 {
-	env.load_module_function("Device", "frame_count", device_frame_count);
-	env.load_module_function("Device", "last_delta_time", device_last_delta_time);
-	env.load_module_function("Device", "start", device_start);
-	env.load_module_function("Device", "stop", device_stop);
+	env.load_module_function("Device", "frame_count",              device_frame_count);
+	env.load_module_function("Device", "last_delta_time",          device_last_delta_time);
+	env.load_module_function("Device", "start",                    device_start);
+	env.load_module_function("Device", "stop",                     device_stop);
+	env.load_module_function("Device", "create_resource_package",  device_create_resource_package);
+	env.load_module_function("Device", "destroy_resource_package", device_destroy_resource_package);
 }
 
 } // namespace crown

+ 57 - 135
engine/lua/LuaEnvironment.cpp

@@ -44,20 +44,17 @@ CE_EXPORT int luaopen_libcrown(lua_State* /*L*/)
 	load_int_setting(*env);
 	load_float_setting(*env);
 	load_string_setting(*env);
-
 	load_vec2(*env);
 	load_vec3(*env);
 	load_mat4(*env);
 	load_quat(*env);
 	load_math(*env);
-
 	load_mouse(*env);
 	load_keyboard(*env);
 	load_accelerometer(*env);
-
 	load_device(*env);
-
 	load_window(*env);
+	load_resource_package(*env);
 
 	return 1;
 }
@@ -81,13 +78,9 @@ static int crown_lua_require(lua_State* L)
 }
 
 //-----------------------------------------------------------------------------
-LuaEnvironment::LuaEnvironment() :
-	m_state(luaL_newstate()),
-	m_is_used(false)
+LuaEnvironment::LuaEnvironment()
+	: m_state(luaL_newstate()), m_is_used(false)
 {
-	// Open Lua default libraries
-	string::strncpy(m_error_buffer, "", 1024);
-	string::strncpy(m_tmp_buffer, "", 1024);
 }
 
 //-----------------------------------------------------------------------------
@@ -117,17 +110,6 @@ void LuaEnvironment::init()
 
 	lua_pop(m_state, 1);
 
-	// load_buffer(class_system, string::strlen(class_system));
-	// execute(0, 0);
-	// load_buffer(commands_list, string::strlen(commands_list));
-	// execute(0, 0);
-	// load_buffer(get_cmd_by_name, string::strlen(get_cmd_by_name));
-	// execute(0, 0);
-	// load_buffer(tmp_print_table, string::strlen(tmp_print_table));
-	// execute(0, 0);
-	// load_buffer(count_all, string::strlen(count_all));
-	// execute(0, 0);
-
 	m_is_used = true;
 }
 
@@ -135,37 +117,61 @@ void LuaEnvironment::init()
 void LuaEnvironment::shutdown()
 {
 	lua_close(m_state);
-
 	m_is_used = false;
 }
 
 //-----------------------------------------------------------------------------
-const char* LuaEnvironment::error()
-{	
-	string::strncpy(m_tmp_buffer, m_error_buffer, 1024);
-	string::strncpy(m_error_buffer, "", 1024);
+bool LuaEnvironment::load_and_execute(const char* res_name)
+{
+	CE_ASSERT_NOT_NULL(res_name);
+
+	ResourceManager* resman = device()->resource_manager();
+
+	// Load the resource
+	ResourceId res_id = resman->load("lua", res_name);
+	resman->flush();
+	LuaResource* lr = (LuaResource*) resman->data(res_id);
+	
+	lua_getglobal(m_state, "debug");
+	lua_getfield(m_state, -1, "traceback");
+	if (luaL_loadbuffer(m_state, (const char*) lr->code(), lr->size(), res_name) == 0)
+	{
+		if (lua_pcall(m_state, 0, 0, -2) == 0)
+		{
+			// Unloading is OK since the script data has been copied to Lua
+			resman->unload(res_id);
+			lua_pop(m_state, 2); // Pop debug.traceback
+			return true;
+		}
+	}
 
-	return m_tmp_buffer;
+	error();
+	lua_pop(m_state, 2); // Pop debug.traceback
+	return false;
 }
 
 //-----------------------------------------------------------------------------
-void LuaEnvironment::load(const LuaResource* lr)
+void LuaEnvironment::load_module_function(const char* module, const char* name, const lua_CFunction func)
 {
-	CE_ASSERT_NOT_NULL(lr);
+	luaL_Reg entry[2];
 
-	if (luaL_loadbuffer(m_state, (const char*) lr->code(), lr->size(), "") != 0)
-	{
-		lua_error();
-	}
+	entry[0].name = name;
+	entry[0].func = func;
+	entry[1].name = NULL;
+	entry[1].func = NULL;
 
-	if (lua_pcall(m_state, 0, 0, 0) != 0)
-	{
-		lua_error();
-	}
+	luaL_register(m_state, module, entry);
+}
+
+//-----------------------------------------------------------
+void LuaEnvironment::load_module_enum(const char* /*module*/, const char* name, uint32_t value)
+{
+	lua_pushinteger(m_state, value);
+	lua_setfield(m_state, -2, name);
 }
 
 //-----------------------------------------------------------------------------
-void LuaEnvironment::call_global(const char* func, uint8_t argc, ...)
+bool LuaEnvironment::call_global(const char* func, uint8_t argc, ...)
 {
 	CE_ASSERT_NOT_NULL(func);
 
@@ -174,6 +180,8 @@ void LuaEnvironment::call_global(const char* func, uint8_t argc, ...)
 	va_list vl;
 	va_start(vl, argc);
 
+	lua_getglobal(m_state, "debug");
+	lua_getfield(m_state, -1, "traceback");
 	lua_getglobal(m_state, func);
 
 	for (uint8_t i = 0; i < argc; i++)
@@ -196,110 +204,24 @@ void LuaEnvironment::call_global(const char* func, uint8_t argc, ...)
 
 	va_end(vl);
 
-	if (lua_pcall(m_state, argc, 0, 0) != 0)
+	if (lua_pcall(m_state, argc, 0, -argc - 2) != 0)
 	{
-		lua_error();
+		error();
+		lua_pop(m_state, 2); // Pop debug.traceback
+		return false;
 	}
-}
 
-//-----------------------------------------------------------------------------
-void LuaEnvironment::lua_error()
-{
-	string::strncpy(m_error_buffer, "", 1024);
-	string::strncpy(m_error_buffer, lua_tostring(m_state, -1), 1024);
-}
+	lua_pop(m_state, 2); // Pop debug.traceback
 
-//-----------------------------------------------------------------------------
-void LuaEnvironment::load_module_function(const char* module, const char* name, const lua_CFunction func)
-{
-	luaL_Reg entry[2];
-
-	entry[0].name = name;
-	entry[0].func = func;
-	entry[1].name = NULL;
-	entry[1].func = NULL;
-
-	luaL_register(m_state, module, entry);
+	return true;
 }
 
-//-----------------------------------------------------------
-void LuaEnvironment::load_module_enum(const char* /*module*/, const char* name, uint32_t value)
+//-----------------------------------------------------------------------------
+void LuaEnvironment::error()
 {
-	lua_pushinteger(m_state, value);
-	lua_setfield(m_state, -2, name);
+	const char* msg = lua_tostring(m_state, -1);
+	Log::e(msg);
+	lua_pop(m_state, 1);
 }
 
-const char* LuaEnvironment::class_system =  "function class(klass, super) "
-    										"	if not klass then "
-        									"		klass = {} "
-                							"		local meta = {} "
-        									"		meta.__call = function(self, ...) "
-            								"			local object = {} "
-            								"			setmetatable(object, klass) "
-            								"			if object.init then object:init(...) end "
-            								"			return object "
-       										"		end "
-        									"		setmetatable(klass, meta) "
-    										"	end "  
-    										"	if super then "
-        									"		for k,v in pairs(super) do "
-            								"			klass[k] = v "
-        									"		end "
-    										"	end "
-    										"	klass.__index = klass "
-    										"	return klass "
-											"end";
-
-
-const char* LuaEnvironment::commands_list = "function get_all_commands() "
-											"	local cmds = {}; "
-											"	for class_name,class in pairs(_G) do "
-											"		if type(class) == 'table' then "
-			 								"			for func_name,func in pairs(class) do "
-			 								"				if type(func) == 'function' then "
-											"					cmds[#cmds+1] = class_name .. '.' .. func_name "
-											"				end "
-											"			end "
-											"		end "
-											"	end "
-											"	return cmds "
-											"end";
-
-const char* LuaEnvironment::get_cmd_by_name = 	"function get_command_by_name(text) "
-												"	local cmds = get_all_commands() "
-												"	local results = {} "
-												"	local index = 0 "
-												"	for i,cmd in pairs(cmds) do "
-												"		if string.find(cmd, text) then "
-												"			results[index] = cmds[i] "
-												"			index = index + 1 "
-												"		end "
-												"	end "
-												"	return results "
-												"end";
-
-const char* LuaEnvironment::tmp_print_table =	"function print_table(table) "												
-												"	for k,v in pairs(table) do "
-												"		print(v) "
-												"	end "
-												"end";
-
-const char* LuaEnvironment::count_all = 	"function count_all(f) "
-											"	local seen = {} "
-											"	local count_table "
-											"	count_table = function(t) "
-											"		if seen[t] then return end "
-											"		f(t) "
-											"		seen[t] = true "
-											"		for k,v in pairs(t) do "
-											"			if type(v) == 'table' then "
-											"				count_table(v) "
-											"			elseif type(v) == 'userdata' then "
-											"				f(v) "
-											"			end "
-											"		end "
-											"	end "
-											"	count_table(_G) "
-											"end";
-
 } // namespace crown

+ 13 - 19
engine/lua/LuaEnvironment.h

@@ -53,16 +53,9 @@ public:
 	/// Close Lua state and shutdown LuaEnvironment
 	void					shutdown();
 
-	const char*				error();
-
-	/// Loads and execute the given @a lr lua script resource.
-	void					load(const LuaResource* lr);
-
-	/// Calls the global function @a func with @a argc argument number.
-	/// Each argument is a pair (type, value).
-	/// Example call:
-	/// call_global("myfunc", 1, ARGUMENT_FLOAT, 3.14f)
-	void					call_global(const char* func, uint8_t argc, ...);
+	/// Loads and execute the given @a res_name Lua resource, returns
+	/// true if success, false otherwise.
+	bool					load_and_execute(const char* res_name);
 
 	/// Load a function which will be used in Lua. @a module is the name of table contenitor,
 	/// @a name is the name of function in module and @func is the pointer to the function.
@@ -74,9 +67,17 @@ public:
 	/// @a name is module's name that refears _value_ and @value is an unsigned integer
 	void					load_module_enum(const char* module, const char* name, uint32_t value);
 
+	/// Calls the global function @a func with @a argc argument number.
+	/// Each argument is a pair (type, value).
+	/// Example call:
+	/// call_global("myfunc", 1, ARGUMENT_FLOAT, 3.14f)
+	/// Returns true if success, false otherwise
+	bool					call_global(const char* func, uint8_t argc, ...);
+
+	void					error();
+
 private:
 
-	void					lua_error();
 	// Disable copying
 							LuaEnvironment(const LuaEnvironment&);
 	LuaEnvironment& 		operator=(const LuaEnvironment&);
@@ -87,14 +88,6 @@ private:
 
 	/// LuaEnvironment is used right now?
 	bool					m_is_used;
-
-	char					m_error_buffer[1024];
-	char					m_tmp_buffer[1024];
-	static const char* 		class_system;
-	static const char*		commands_list;
-	static const char*		get_cmd_by_name;
-	static const char*		tmp_print_table;
-	static const char*		count_all;
 };
 
 
@@ -114,5 +107,6 @@ void load_accelerometer(LuaEnvironment& env);
 void load_camera(LuaEnvironment& env);
 void load_device(LuaEnvironment& env);
 void load_window(LuaEnvironment& env);
+void load_resource_package(LuaEnvironment& env);
 
 } // namespace crown

+ 39 - 65
engine/renderers/gl/GLUtils.cpp → engine/lua/LuaResourcePackage.cpp

@@ -24,90 +24,64 @@ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 OTHER DEALINGS IN THE SOFTWARE.
 */
 
-#include "GLUtils.h"
+#include "ResourcePackage.h"
+#include "LuaStack.h"
+#include "LuaEnvironment.h"
 
 namespace crown
 {
 
 //-----------------------------------------------------------------------------
-const GLenum GL::COMPARE_FUNCTION_TABLE[CF_COUNT] =
+CE_EXPORT int resource_package_load(lua_State* L)
 {
-	GL_NEVER,
-	GL_LESS,
-	GL_EQUAL,
-	GL_LEQUAL,
-	GL_GREATER,
-	GL_NOTEQUAL,
-	GL_GEQUAL,
-	GL_ALWAYS
-};
+	LuaStack stack(L);
 
-//-----------------------------------------------------------------------------
-const GLenum GL::BLEND_FUNCTION_TABLE[BF_COUNT] =
-{
-	GL_ZERO,
-	GL_ONE,
-	GL_SRC_COLOR,
-	GL_ONE_MINUS_SRC_COLOR,
-	GL_DST_COLOR,
-	GL_ONE_MINUS_DST_COLOR,
-	GL_SRC_ALPHA,
-	GL_ONE_MINUS_SRC_ALPHA,
-	GL_DST_ALPHA,
-	GL_ONE_MINUS_DST_ALPHA,
-	GL_CONSTANT_COLOR,
-	GL_ONE_MINUS_CONSTANT_COLOR,
-	GL_CONSTANT_ALPHA,
-	GL_ONE_MINUS_CONSTANT_ALPHA,
-	GL_SRC_ALPHA_SATURATE
-};
+	ResourcePackage* package = (ResourcePackage*) stack.get_lightdata(1);
+	package->load();
 
-//-----------------------------------------------------------------------------
-const GLenum GL::BLEND_EQUATION_TABLE[BE_COUNT] =
-{
-	GL_FUNC_ADD,
-	GL_FUNC_SUBTRACT,
-	GL_FUNC_REVERSE_SUBTRACT,
-	GL_MIN,
-	GL_MAX
-};
+	return 0;
+}
 
 //-----------------------------------------------------------------------------
-const GLenum GL::TEXTURE_WRAP_TABLE[TW_COUNT] =
+CE_EXPORT int resource_package_unload(lua_State* L)
 {
-	GL_REPEAT,
-	GL_CLAMP,
-	GL_CLAMP_TO_EDGE,
-	GL_CLAMP_TO_BORDER
-};
+	LuaStack stack(L);
+
+	ResourcePackage* package = (ResourcePackage*) stack.get_lightdata(1);
+	package->unload();
+
+	return 0;
+}
 
 //-----------------------------------------------------------------------------
-const GLenum GL::TEXTURE_MIN_FILTER_TABLE[TF_COUNT] =
+CE_EXPORT int resource_package_flush(lua_State* L)
 {
-	GL_NEAREST,
-	GL_LINEAR,
-	GL_NEAREST_MIPMAP_LINEAR,
-	GL_LINEAR_MIPMAP_LINEAR,
-	GL_LINEAR_MIPMAP_LINEAR
-};
+	LuaStack stack(L);
+
+	ResourcePackage* package = (ResourcePackage*) stack.get_lightdata(1);
+	package->flush();
+
+	return 0;
+}
 
 //-----------------------------------------------------------------------------
-const GLenum GL::TEXTURE_MAG_FILTER_TABLE[TF_COUNT] =
+CE_EXPORT int resource_package_has_loaded(lua_State* L)
 {
-	GL_NEAREST,
-	GL_LINEAR,
-	GL_LINEAR,
-	GL_LINEAR,
-	GL_LINEAR
-};
+	LuaStack stack(L);
+
+	ResourcePackage* package = (ResourcePackage*) stack.get_lightdata(1);
+	stack.push_bool(package->has_loaded());
+
+	return 1;
+}
 
 //-----------------------------------------------------------------------------
-const GLenum GL::POLYGON_MODE_TABLE[PM_COUNT] =
+void load_resource_package(LuaEnvironment& env)
 {
-	GL_POINT,
-	GL_LINE,
-	GL_FILL
-};
+	env.load_module_function("ResourcePackage", "load",       resource_package_load);
+	env.load_module_function("ResourcePackage", "unload",     resource_package_unload);
+	env.load_module_function("ResourcePackage", "flush",      resource_package_flush);
+	env.load_module_function("ResourcePackage", "has_loaded", resource_package_has_loaded);
+}
 
 } // namespace crown
-

+ 1 - 1
engine/lua/LuaStack.h

@@ -115,7 +115,7 @@ public:
 	//-----------------------------------------------------------------------------
 	bool get_bool(int32_t index)
 	{
-		return (bool) luaL_checkinteger(m_state, index);
+		return (bool) lua_toboolean(m_state, index);
 	}
 
 	//-----------------------------------------------------------------------------

+ 32 - 5
engine/lua/LuaWindow.cpp

@@ -109,21 +109,45 @@ CE_EXPORT int window_move(lua_State* L)
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int window_show_cursor(lua_State* L)
+CE_EXPORT int window_minimize(lua_State* /*L*/)
+{
+	device()->window()->minimize();
+	return 0;
+}
+
+//-----------------------------------------------------------------------------
+CE_EXPORT int window_restore(lua_State* /*L*/)
+{
+	device()->window()->restore();
+	return 0;
+}
+
+//-----------------------------------------------------------------------------
+CE_EXPORT int window_is_resizable(lua_State* L)
+{
+	LuaStack stack(L);
+
+	stack.push_bool(device()->window()->is_resizable());
+
+	return 1;
+}
+
+//-----------------------------------------------------------------------------
+CE_EXPORT int window_set_resizable(lua_State* L)
 {
 	LuaStack stack(L);
 
-	device()->window()->show_cursor();
+	device()->window()->set_resizable(stack.get_bool(1));
 
 	return 0;
 }
 
 //-----------------------------------------------------------------------------
-CE_EXPORT int window_hide_cursor(lua_State* L)
+CE_EXPORT int window_show_cursor(lua_State* L)
 {
 	LuaStack stack(L);
 
-	device()->window()->hide_cursor();
+	device()->window()->show_cursor(stack.get_bool(1));
 
 	return 0;
 }
@@ -189,8 +213,11 @@ void load_window(LuaEnvironment& env)
 	env.load_module_function("Window", "get_position",	window_get_position);
 	env.load_module_function("Window", "resize",		window_resize);
 	env.load_module_function("Window", "move",			window_move);
+	env.load_module_function("Window", "minimize",		window_minimize);
+	env.load_module_function("Window", "restore",		window_restore);
+	env.load_module_function("Window", "is_resizable",	window_is_resizable);
+	env.load_module_function("Window", "set_resizable",	window_set_resizable);
 	env.load_module_function("Window", "show_cursor",	window_show_cursor);
-	env.load_module_function("Window", "hide_cursor",	window_hide_cursor);
 	env.load_module_function("Window", "get_cursor_xy",	window_get_cursor_xy);
 	env.load_module_function("Window", "set_cursor_xy",	window_set_cursor_xy);
 	env.load_module_function("Window", "title",			window_title);

+ 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

+ 8 - 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
 {
@@ -46,6 +47,8 @@ namespace crown
 
 	#define snprintf _snprintf
 
+	#define Thread os::Thread
+
 	#undef MK_SHIFT
 	#undef MK_ALT
 #elif defined(ANDROID)
@@ -105,6 +108,9 @@ bool			delete_directory(const char* path);
 /// Does not follow symbolic links.
 void			list_files(const char* path, Vector<DynamicString>& files);
 
+/// Returns os-dependent path from os-indipendent @a path
+const char*		normalize_path(const char* path);
+
 //-----------------------------------------------------------------------------
 // OS ambient variables
 //-----------------------------------------------------------------------------
@@ -150,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
 

+ 44 - 24
engine/renderers/Texture.h → engine/os/OsEvents.h

@@ -31,38 +31,58 @@ OTHER DEALINGS IN THE SOFTWARE.
 namespace crown
 {
 
-// Max number of textures a renderer can hold.
-const uint32_t MAX_TEXTURES = 4096;
+/// __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;
+};
 
-enum TextureMode
+/// __OsKeyboardEvent__ represents an event fired by keyboard.
+/// it is processed by InputManager.
+struct OsKeyboardEvent
 {
-	TM_MODULATE	= 0,	// Multiplies texel color by the geometry color after lighting
-	TM_REPLACE	= 1,	// Replaces the fragment color with the texel color
-	TM_DECAL	= 2,	// WTF?
-	TM_BLEND	= 3,	// Blends the texel color with a constant blending color
-	TM_ADD		= 4,	// Adds the texel color to the fragment color
-	TM_COUNT
+	uint32_t key;
+	uint32_t modifier;
 };
 
-/// Enumerates the hardware filter to use when applying a texture
-enum TextureFilter
+/// __OsTouchEvent__ represents an event fired by touch screen.
+/// It is processed by InputManager.
+struct OsTouchEvent
 {
-	TF_NEAREST		= 0,
-	TF_LINEAR		= 1,
-	TF_BILINEAR		= 2,
-	TF_TRILINEAR	= 3,
-	TF_ANISOTROPIC	= 4,
-	TF_COUNT
+	uint32_t pointer_id;
+	uint32_t x;
+	uint32_t y;
 };
 
-/// Enumerates the wrapping mode to use when applying a texture
-enum TextureWrap
+/// __OsAccelerometerEvent__ represents an event fired by accelerometer.
+/// It is processed by InputManager.
+struct OsAccelerometerEvent
 {
-	TW_REPEAT			= 0,
-	TW_CLAMP			= 1,
-	TW_CLAMP_TO_EDGE	= 2,
-	TW_CLAMP_TO_BORDER	= 3,
-	TW_COUNT
+	float x;
+	float y;
+	float z;	
 };
 
 } // namespace crown

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

@@ -26,12 +26,26 @@ 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_initCrown(JNIEnv* /*env*/, jobject /*obj*/)
+{
+	crown::init();
+}
+
+//-----------------------------------------------------------------------------
+extern "C" JNIEXPORT void JNICALL Java_crown_android_CrownLib_shutdownCrown(JNIEnv* /*env*/, jobject /*obj*/)
+{
+	crown::shutdown();
+}
+
+//-----------------------------------------------------------------------------
+extern "C" JNIEXPORT void JNICALL Java_crown_android_CrownLib_initDevice(JNIEnv* /*env*/, jobject /*obj*/)
 {
 	const char* argv[] = { "crown-android" };
 
@@ -39,27 +53,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

+ 38 - 18
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,9 +48,7 @@ namespace crown
 namespace os
 {
 
-static timespec			base_time;
-static uint32_t			window_width;
-static uint32_t			window_height;
+static timespec	base_time;
 
 //-----------------------------------------------------------------------------
 void printf(const char* string, ...)
@@ -201,6 +200,30 @@ void list_files(const char* path, Vector<DynamicString>& files)
 	closedir(dir);
 }
 
+//-----------------------------------------------------------------------------
+const char* normalize_path(const char* path)
+{
+	static char norm[MAX_PATH_LENGTH];
+	char* cur = norm;
+
+	while ((*path) != '\0')
+	{
+		if ((*path) == '\\')
+		{
+			(*cur) = PATH_SEPARATOR;
+		}
+		else
+		{
+			(*cur) = (*path);
+		}
+
+		path++;
+		cur++;
+	}
+
+	return norm;
+}
+
 //-----------------------------------------------------------------------------
 const char* get_cwd()
 {
@@ -285,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;
 }
 
 //-----------------------------------------------------------------------------

+ 14 - 2
engine/os/android/Config.h

@@ -26,7 +26,7 @@ OTHER DEALINGS IN THE SOFTWARE.
 
 #define CROWN_VERSION_MAJOR 0 
 #define CROWN_VERSION_MINOR 1 
-#define CROWN_VERSION_MICRO 11
+#define CROWN_VERSION_MICRO 12
 
 #define CROWN_DEVELOPMENT
 
@@ -35,4 +35,16 @@ OTHER DEALINGS IN THE SOFTWARE.
 	#define PRIu64 "llu"
 	#define PRIi64 "lli"
 	#define PRIx64 "llx"
-#endif
+#endif
+
+#define CROWN_MAX_TEXTURE_UNITS		8
+#define CROWN_MAX_TEXTURES			32
+#define CROWN_MAX_RENDER_TARGETS	32
+#define CROWN_MAX_VERTEX_BUFFERS	1024
+#define CROWN_MAX_INDEX_BUFFERS		1024
+#define CROWN_MAX_SHADERS			1024
+#define CROWN_MAX_GPU_PROGRAMS		1024
+#define CROWN_MAX_UNIFORMS			128
+
+// Including NUL character
+#define CROWN_MAX_UNIFORM_NAME_LENGTH	64

+ 0 - 58
engine/os/android/MainThread.java

@@ -1,58 +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.
-*/
-
-package crown.android;
-
-import android.view.SurfaceHolder;
-
-public class MainThread extends Thread
-{
-	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();
-	}
-}

+ 36 - 23
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);
 	}
-
 }
 
 //-----------------------------------------------------------------------------
@@ -96,12 +86,28 @@ void OsWindow::move(uint32_t /*x*/, uint32_t /*y*/)
 }
 
 //-----------------------------------------------------------------------------
-void OsWindow::show_cursor()
+void OsWindow::minimize()
+{
+}
+
+//-----------------------------------------------------------------------------
+void OsWindow::restore()
+{
+}
+
+//-----------------------------------------------------------------------------
+bool OsWindow::is_resizable() const
+{
+	return false;
+}
+
+//-----------------------------------------------------------------------------
+void OsWindow::set_resizable(bool /*resizeable*/)
 {
 }
 
 //-----------------------------------------------------------------------------
-void OsWindow::hide_cursor()
+void OsWindow::show_cursor(bool /*show*/)
 {
 }
 
@@ -129,15 +135,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

+ 12 - 4
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
 {
@@ -58,11 +59,20 @@ public:
 	/// Stub method, does nothing under Android.
 	void			move(uint32_t x, uint32_t y);
 
+	/// Stub method, does nothing under Android.	
+	void			minimize();
+
 	/// Stub method, does nothing under Android.
-	void			show_cursor();
+	void			restore();
+
+	/// Returns always false.
+	bool			is_resizable() const;
+
+	/// Stub method, does nothing under Android.	
+	void			set_resizable(bool resizeable);
 
 	/// Stub method, does nothing under Android.
-	void			hide_cursor();
+	void			show_cursor(bool show);
 
 	/// Stub method, does nothing under Android.
 	void			get_cursor_xy(int32_t& x, int32_t& y);
@@ -81,8 +91,6 @@ public:
 
 private:
 
-	ANativeWindow*	m_window;
-
 	uint32_t		m_x;
 	uint32_t		m_y;
 	uint32_t		m_width;

+ 19 - 35
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,39 +60,31 @@ public class CrownActivity extends Activity
 	private CrownTouch 			mTouch;
 	private CrownSensor			mSensor;
 
-	// Graphic attributes
-	static CrownSurfaceView		mWindow;
+	private CrownSurfaceView 	mView;
+
 
 //-----------------------------------------------------------------------------
     public void onCreate(Bundle savedInstanceState)
     {
         super.onCreate(savedInstanceState);
 
+        // Initializes low-level systems (memory, os etc.)
+        CrownLib.initCrown();
+
 		// init AssetManager
 		mAssetManager = getAssets();
 		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 +92,29 @@ 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();
+
+		Log.i(TAG, "Crown Activity paused");
 	}
 
 //-----------------------------------------------------------------------------
 	public void onDestroy()
 	{
 		super.onDestroy();
+
+		CrownLib.shutdownDevice();
+		CrownLib.shutdownCrown();
 	}
 
 //-----------------------------------------------------------------------------
@@ -133,10 +123,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


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

@@ -36,22 +36,36 @@ public class CrownLib
 		System.loadLibrary("luajit-5.1");
 		System.loadLibrary("crown");
 	}
+
+	// Crown functions
+	public static native void		initCrown();
+	public static native void		shutdownCrown();
 	
 	// Device functions
-	public static native void 		init();
+	public static native void 		initDevice();
+	public static native void		shutdownDevice();
+	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);	
 }

+ 28 - 27
engine/renderers/VertexFormat.cpp → engine/os/android/java/CrownMainThread.java

@@ -24,44 +24,45 @@ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 OTHER DEALINGS IN THE SOFTWARE.
 */
 
-#include "Types.h"
-#include "VertexFormat.h"
+package crown.android;
 
-namespace crown
+import android.util.Log;
+import android.view.SurfaceHolder;
+
+///
+public class CrownMainThread extends Thread
 {
+	private SurfaceHolder mSurfaceHolder;
+
+	private boolean mPaused;
+
 
 //-----------------------------------------------------------------------------
-size_t Vertex::bits_per_vertex(VertexFormat format)
-{
-	return bytes_per_vertex(format) * 8;
-}
+	public CrownMainThread(SurfaceHolder holder)
+	{
+		super();
+		mSurfaceHolder = holder;
+	}
 
 //-----------------------------------------------------------------------------
-size_t Vertex::bytes_per_vertex(VertexFormat format)
-{
-	switch (format)
+	@Override
+	public void run()
 	{
-		case VF_XY_FLOAT_32:
-		case VF_UV_FLOAT_32:
-		{
-			return 8;
-		}
-		case VF_XYZ_FLOAT_32:
-		case VF_UVT_FLOAT_32:
-		case VF_XYZ_NORMAL_FLOAT_32:
+		CrownLib.createWindow(mSurfaceHolder.getSurface());
+
+		if (!CrownLib.isDeviceInit())
 		{
-			return 12;
+			CrownLib.initDevice();
 		}
-		case VF_XYZ_UV_XYZ_NORMAL_FLOAT_32:
+		else
 		{
-			return 32;
+			CrownLib.initRenderer();
+			CrownLib.unpauseDevice();
 		}
-		default:
+
+		while (CrownLib.isDeviceRunning() && !CrownLib.isDevicePaused())
 		{
-			return 0;
+			CrownLib.frame();
 		}
 	}
-}
-
-} // namespace crown
-
+}

+ 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;

+ 27 - 0
engine/os/linux/LinuxOS.cpp

@@ -25,6 +25,7 @@ OTHER DEALINGS IN THE SOFTWARE.
 */
 
 #include "Assert.h"
+#include <X11/Xlib.h>
 #include <cstdarg>
 #include <cstdio>
 #include <cstdlib>
@@ -206,6 +207,30 @@ void list_files(const char* path, Vector<DynamicString>& files)
 	closedir(dir);
 }
 
+//-----------------------------------------------------------------------------
+const char* normalize_path(const char* path)
+{
+	static char norm[MAX_PATH_LENGTH];
+	char* cur = norm;
+
+	while ((*path) != '\0')
+	{
+		if ((*path) == '\\')
+		{
+			(*cur) = PATH_SEPARATOR;
+		}
+		else
+		{
+			(*cur) = (*path);
+		}
+
+		path++;
+		cur++;
+	}
+
+	return norm;
+}
+
 //-----------------------------------------------------------------------------
 const char* get_cwd()
 {
@@ -249,6 +274,8 @@ const char* get_env(const char* env)
 //-----------------------------------------------------------------------------
 void init_os()
 {
+	XInitThreads();
+
 	// Initilize the base time
 	clock_gettime(CLOCK_MONOTONIC, &base_time);
 }

+ 58 - 22
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
 {
@@ -99,6 +100,7 @@ OsWindow::OsWindow(uint32_t width, uint32_t height, uint32_t parent) :
 	m_y(0),
 	m_width(width),
 	m_height(height),
+	m_resizable(true),
 	m_x11_detectable_autorepeat(false),
 	m_x11_hidden_cursor(None)
 {
@@ -214,15 +216,49 @@ void OsWindow::move(uint32_t x, uint32_t y)
 }
 
 //-----------------------------------------------------------------------------
-void OsWindow::show_cursor()
+void OsWindow::minimize()
 {
-	XDefineCursor(m_x11_display, m_x11_window, None);
+	XIconifyWindow(m_x11_display, m_x11_window, DefaultScreen(m_x11_display));
 }
 
 //-----------------------------------------------------------------------------
-void OsWindow::hide_cursor()
+void OsWindow::restore()
 {
-	XDefineCursor(m_x11_display, m_x11_window, m_x11_hidden_cursor);
+	XMapRaised(m_x11_display, m_x11_window);
+}
+
+//-----------------------------------------------------------------------------
+bool OsWindow::is_resizable() const
+{
+	return m_resizable;
+}
+
+//-----------------------------------------------------------------------------
+void OsWindow::set_resizable(bool resizable)
+{
+	XSizeHints hints;
+	hints.flags = PMinSize | PMaxSize;
+	hints.min_width = resizable ? 1 : m_width;
+	hints.min_height = resizable ? 1 : m_height;
+	hints.max_width = resizable ? 65535 : m_width;
+	hints.max_height = resizable ? 65535 : m_height;
+
+	XSetWMNormalHints(m_x11_display, m_x11_window, &hints);
+
+	m_resizable = resizable;
+}
+
+//-----------------------------------------------------------------------------
+void OsWindow::show_cursor(bool show)
+{
+	if (show)
+	{
+		XDefineCursor(m_x11_display, m_x11_window, None);
+	}
+	else
+	{
+		XDefineCursor(m_x11_display, m_x11_window, m_x11_hidden_cursor);
+	}
 }
 
 //-----------------------------------------------------------------------------
@@ -271,8 +307,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 +329,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 +389,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)

+ 8 - 2
engine/os/linux/OsWindow.h

@@ -54,8 +54,13 @@ public:
 	void			resize(uint32_t width, uint32_t height);
 	void			move(uint32_t x, uint32_t y);
 
-	void			show_cursor();
-	void			hide_cursor();
+	void			minimize();
+	void			restore();
+
+	bool			is_resizable() const;
+	void			set_resizable(bool resizable);
+
+	void			show_cursor(bool show);
 
 	void			get_cursor_xy(int32_t& x, int32_t& y);
 	void			set_cursor_xy(int32_t x, int32_t y);
@@ -75,6 +80,7 @@ private:
 	uint32_t		m_y;
 	uint32_t		m_width;
 	uint32_t		m_height;
+	bool			m_resizable;
 
 	bool			m_x11_detectable_autorepeat;
 	Cursor			m_x11_hidden_cursor;

+ 3 - 7
engine/os/linux/main.cpp

@@ -28,23 +28,19 @@ OTHER DEALINGS IN THE SOFTWARE.
 
 int main(int argc, char** argv)
 {
-	crown::os::init_os();
+	crown::init();
 
 	crown::Device* engine = crown::device();
-
 	if (!engine->init(argc, argv))
 	{
-		exit(-1);
+		exit(EXIT_FAILURE);
 	}
 
-	// Main loop
 	while (engine->is_running())
 	{
 		engine->frame();
 	}
 
 	engine->shutdown();
-
-	return 0;
+	crown::shutdown();
 }
-

+ 320 - 0
engine/os/linux/main2.cpp

@@ -0,0 +1,320 @@
+/*
+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 "Crown.h"
+#include "FPSSystem.h"
+
+using namespace crown;
+
+Renderer* r;
+IndexBufferId monkey_ib;
+VertexBufferId monkey_vb;
+IndexBufferId cube_ib;
+VertexBufferId cube_vb;
+IndexBufferId cone_ib;
+VertexBufferId cone_vb;
+
+GPUProgramId default_program;
+GPUProgramId texture_program;
+Camera* camera;
+FPSSystem* fps;
+
+TextureId grass_texture;
+TextureId lightmap_texture;
+IndexBufferId quad_ib;
+VertexBufferId quad_vb;
+
+UniformId u_albedo_0;
+UniformId u_lightmap_0;
+UniformId u_brightness;
+
+static float quad_vertices[] =
+{
+	-1.0f, -1.0f, 0.0f, 
+	 0.0f, 0.0f, 1.0f,
+	 1.0f, 1.0f, 1.0f, 1.0f,
+	 0.0f, 0.0f,
+
+	 1.0f, -1.0f, 0.0f,
+	 0.0f, 0.0f, 1.0f,
+	 1.0f, 1.0f, 1.0f, 1.0f,
+	 1.0f, 0.0f,
+
+	 1.0f,  1.0f, 0.0f,
+	 0.0f, 0.0f, 1.0f,
+	 1.0f, 1.0f, 1.0f, 1.0f,
+	 1.0f, 1.0f,
+
+	-1.0f,  1.0f, 0.0f,
+	 0.0f, 0.0f, 1.0f,
+	 1.0f, 1.0f, 1.0f, 1.0f,
+	 0.0f, 1.0f
+};
+
+static uint16_t quad_indices[] =
+{
+	0, 1, 3,
+	1, 2, 3
+};
+
+static const char* default_vertex =
+	"in vec4           a_position;"
+	"in vec4           a_normal;"
+	"in vec2           a_tex_coord0;"
+	"in vec4           a_color;"
+
+	"uniform mat4      u_model;"
+	"uniform mat4      u_model_view_projection;"
+
+	"varying out vec2  tex_coord0;"
+	"varying out vec4  color;"
+
+	"void main(void)"
+	"{"
+	"	tex_coord0 = a_tex_coord0;"
+	"   color = a_color;"
+	"	gl_Position = u_model_view_projection * a_position;"
+	"}";
+
+static const char* default_fragment = 
+	"void main(void)"
+	"{"
+	"	gl_FragColor = vec4(1, 0, 0, 0);"
+	"}";
+
+static const char* texture_fragment = 
+	"in vec2            tex_coord0;"
+	"in vec4            color;"
+
+	"uniform sampler2D  u_albedo_0;"
+	"uniform sampler2D  u_lightmap_0;"
+	"uniform float      u_brightness;"
+
+	"void main(void)"
+	"{"
+	"	gl_FragColor = texture(u_albedo_0, tex_coord0);"
+	"}";
+
+void draw(float dt)
+{
+	Mat4 pose; pose.load_identity();
+
+	fps->update(dt);
+	fps->set_view_by_cursor();
+
+	//-----------------------
+	r->set_layer_view(0, camera->view_matrix());
+	r->set_layer_projection(0, camera->projection_matrix());
+	r->set_layer_viewport(0, 0, 0, 1000, 625);
+	r->set_layer_clear(0, CLEAR_COLOR | CLEAR_DEPTH, Color4::LIGHTBLUE, 1.0f);
+
+	r->set_state(STATE_DEPTH_WRITE | STATE_COLOR_WRITE | STATE_CULL_CCW);
+	r->commit(0);
+
+	static uint64_t prim = STATE_PRIMITIVE_TRIANGLES;
+	if (device()->keyboard()->key_pressed(KC_z))
+	{
+		prim = STATE_PRIMITIVE_TRIANGLES;
+	}
+	else if (device()->keyboard()->key_pressed(KC_x))
+	{
+		prim = STATE_PRIMITIVE_POINTS;
+	}
+	else if (device()->keyboard()->key_pressed(KC_c))
+	{
+		prim = STATE_PRIMITIVE_LINES;
+	}
+
+	static uint32_t filter = TEXTURE_FILTER_NEAREST;
+	if (device()->keyboard()->key_pressed(KC_1))
+	{
+		filter = TEXTURE_FILTER_NEAREST;
+	}
+	else if (device()->keyboard()->key_pressed(KC_2))
+	{
+		filter = TEXTURE_FILTER_LINEAR;
+	}
+	else if (device()->keyboard()->key_pressed(KC_3))
+	{
+		filter = TEXTURE_FILTER_BILINEAR;
+	}
+	else if (device()->keyboard()->key_pressed(KC_4))
+	{
+		filter = TEXTURE_FILTER_TRILINEAR;
+	}
+	static float brightness = 1.0f;
+	if (device()->keyboard()->key_pressed(KC_UP))
+	{
+		brightness += 0.01f;
+	}
+	else if (device()->keyboard()->key_pressed(KC_DOWN))
+	{
+		brightness += -0.01f;
+	}
+	if (brightness > 1.0f)
+		brightness = 1.0f;
+
+	//-----------------------
+	// r->set_state(prim | STATE_DEPTH_WRITE | STATE_COLOR_WRITE | STATE_CULL_CW);
+	// r->set_vertex_buffer(monkey_vb);
+	// r->set_index_buffer(monkey_ib);
+	// r->set_program(default_program);
+	// pose.set_translation(Vec3(-3, 0, -3));
+	// r->set_pose(pose);
+	// r->commit(0);
+
+	//-----------------------
+	r->set_state(prim | STATE_DEPTH_WRITE | STATE_COLOR_WRITE | STATE_CULL_CW);
+	r->set_vertex_buffer(cube_vb);
+	r->set_index_buffer(cube_ib);
+	r->set_program(texture_program);
+	r->set_texture(0, u_albedo_0, grass_texture, filter | TEXTURE_WRAP_CLAMP_EDGE);
+	r->set_texture(1, u_lightmap_0, lightmap_texture, filter | TEXTURE_WRAP_CLAMP_EDGE);
+	r->set_uniform(u_brightness, UNIFORM_FLOAT_1, &brightness, 1);
+
+	pose.set_translation(Vec3(0, 0, -3));
+	r->set_pose(pose);
+	r->commit(0);
+
+	//-----------------------
+	// r->set_state(prim | STATE_DEPTH_WRITE | STATE_COLOR_WRITE | STATE_ALPHA_WRITE | STATE_CULL_CW);
+	// r->set_vertex_buffer(cone_vb);
+	// r->set_index_buffer(cone_ib);
+	// r->set_program(default_program);
+
+	// pose.set_translation(Vec3(3, 0, -3));
+	// r->set_pose(pose);
+	// r->commit(0);
+
+	//-----------------------
+	// r->set_state(prim | STATE_DEPTH_WRITE | STATE_COLOR_WRITE | STATE_ALPHA_WRITE | STATE_CULL_CW);
+	// r->set_vertex_buffer(quad_vb);
+	// r->set_index_buffer(quad_ib);
+	// r->set_program(texture_program);
+	// r->set_texture(0, u_albedo_0, grass_texture, filter | TEXTURE_WRAP_CLAMP_EDGE);
+	// r->set_texture(1, u_lightmap_0, lightmap_texture, filter | TEXTURE_WRAP_CLAMP_EDGE);
+	// r->set_uniform(u_brightness, UNIFORM_FLOAT_1, &brightness, 1);
+
+	// pose.set_translation(Vec3(0, 0, -1));
+	// r->set_pose(pose);
+	// r->commit(0);
+}
+
+int main(int argc, char** argv)
+{
+	crown::init();
+
+	Device* engine = device();
+	engine->init(argc, argv);
+
+	// Load resources
+	ResourceManager* resman = engine->resource_manager();
+	ResourceId texture = resman->load("texture", "ship");
+	ResourceId lightmap = resman->load("texture", "lightmap");
+	ResourceId monkey = resman->load("mesh", "monkey");
+	ResourceId cube = resman->load("mesh", "ship");
+	ResourceId cone = resman->load("mesh", "cone");
+	resman->flush();
+
+	TextureResource* texture_resource = (TextureResource*)resman->data(texture);
+	TextureResource* lightmap_resource = (TextureResource*)resman->data(lightmap);
+	MeshResource* monkey_resource = (MeshResource*)resman->data(monkey);
+	MeshResource* cube_resource = (MeshResource*)resman->data(cube);
+	MeshResource* cone_resource = (MeshResource*)resman->data(cone);
+
+	Log::d("monkey format = %d", monkey_resource->vertex_format());
+	Log::d("monkey vcount = %d", monkey_resource->num_vertices());
+	Log::d("cube format   = %d", cube_resource->vertex_format());
+	Log::d("cube vcount   = %d", cube_resource->num_vertices());
+	Log::d("cone format = %d", cone_resource->vertex_format());
+	Log::d("cone vcount = %d", cone_resource->num_vertices());
+
+	// Create vb/ib
+	r = engine->renderer();
+	monkey_vb = r->create_vertex_buffer(monkey_resource->num_vertices(), monkey_resource->vertex_format(), monkey_resource->vertices());
+	monkey_ib = r->create_index_buffer(monkey_resource->num_indices(), monkey_resource->indices());
+	cube_vb = r->create_vertex_buffer(cube_resource->num_vertices(), cube_resource->vertex_format(), cube_resource->vertices());
+	cube_ib = r->create_index_buffer(cube_resource->num_indices(), cube_resource->indices());
+	cone_vb = r->create_vertex_buffer(cone_resource->num_vertices(), cone_resource->vertex_format(), cone_resource->vertices());
+	cone_ib = r->create_index_buffer(cone_resource->num_indices(), cone_resource->indices());
+
+	// Create texture
+	grass_texture = r->create_texture(texture_resource->width(), texture_resource->height(), texture_resource->format(),
+										texture_resource->data());
+	lightmap_texture = r->create_texture(lightmap_resource->width(), lightmap_resource->height(), lightmap_resource->format(),
+										lightmap_resource->data());
+
+	quad_vb = r->create_vertex_buffer(4, VERTEX_P3_N3_C4_T2, quad_vertices);
+	quad_ib = r->create_index_buffer(6, quad_indices);
+
+	ShaderId default_vs = r->create_shader(SHADER_VERTEX, default_vertex);
+	ShaderId default_fs = r->create_shader(SHADER_FRAGMENT, default_fragment);
+	ShaderId texture_fs = r->create_shader(SHADER_FRAGMENT, texture_fragment);
+
+	u_albedo_0 = r->create_uniform("u_albedo_0", UNIFORM_INTEGER_1, 1);
+	u_lightmap_0 = r->create_uniform("u_lightmap_0", UNIFORM_INTEGER_1, 1);
+	u_brightness = r->create_uniform("u_brightness", UNIFORM_FLOAT_1, 1);
+
+	default_program = r->create_gpu_program(default_vs, default_fs);
+	texture_program = r->create_gpu_program(default_vs, texture_fs);
+
+	// Create camera
+	TempAllocator2048 alloc;
+	camera = CE_NEW(alloc, Camera)(Vec3(0, 0, 3), 90.0f, 16.0f/9.0f);
+	fps = CE_NEW(alloc, FPSSystem)(camera, 3.0f, 2.5f);
+
+	while (engine->is_running())
+	{
+		engine->frame(draw);
+	}
+
+	//resman->unload(mesh);
+	resman->unload(texture);
+	resman->unload(lightmap);
+	resman->unload(monkey);
+	resman->unload(cube);
+	resman->unload(cone);
+	r->destroy_index_buffer(monkey_ib);
+	r->destroy_vertex_buffer(monkey_vb);
+	r->destroy_index_buffer(cube_ib);
+	r->destroy_vertex_buffer(cube_vb);
+	r->destroy_index_buffer(cone_ib);
+	r->destroy_vertex_buffer(cone_vb);
+
+	r->destroy_shader(default_vs);
+	r->destroy_shader(default_fs);
+	r->destroy_shader(texture_fs);
+	r->destroy_gpu_program(default_program);
+	r->destroy_gpu_program(texture_program);
+	r->destroy_vertex_buffer(quad_vb);
+	r->destroy_index_buffer(quad_ib);
+	r->destroy_uniform(u_albedo_0);
+	r->destroy_uniform(u_lightmap_0);
+	r->destroy_uniform(u_brightness);
+
+	engine->shutdown();
+	crown::shutdown();
+}

+ 0 - 60
engine/os/posix/Cond.cpp

@@ -1,60 +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 <string.h>
-
-#include "Cond.h"
-
-namespace crown
-{
-
-//-----------------------------------------------------------------------------
-Cond::Cond()
-{
-	memset(&m_cond, 0, sizeof(pthread_cond_t));
-
-	pthread_cond_init(&m_cond, NULL);
-}
-
-//-----------------------------------------------------------------------------
-Cond::~Cond()
-{
-	pthread_cond_destroy(&m_cond);
-}
-
-//-----------------------------------------------------------------------------
-void Cond::signal()
-{
-	pthread_cond_signal(&m_cond);
-}
-
-//-----------------------------------------------------------------------------
-void Cond::wait(Mutex& mutex)
-{
-	pthread_cond_wait(&m_cond, &(mutex.m_mutex));
-}
-
-} // namespace crown

+ 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

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

@@ -26,74 +26,135 @@ 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");
+	
+	int32_t result = pthread_join(m_handle, NULL);
+	CE_ASSERT(result == 0, "Thread join failed. errno: %d", result);
+
+	m_is_running = false;
+	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)
+{
+	static int32_t result = -1;
+	result = ((Thread*)arg)->run();
+
+	return (void*)&result;
+}
 
-	// Disable copying
-					Thread(const Thread&);
-	Thread&			operator=(const Thread&);
-};
 
-} // namespace crown
+} // namespace crown

+ 2 - 8
engine/os/win/OsWindow.cpp

@@ -206,15 +206,9 @@ void OsWindow::move(uint32_t x, uint32_t y)
 }
 
 //-----------------------------------------------------------------------------
-void OsWindow::show_cursor()
+void OsWindow::show_cursor(bool show)
 {
-	ShowCursor(true);
-}
-
-//-----------------------------------------------------------------------------
-void OsWindow::hide_cursor()
-{
-	ShowCursor(false);
+	ShowCursor(show);
 }
 
 //-----------------------------------------------------------------------------

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

@@ -48,8 +48,7 @@ public:
 	void			resize(uint32_t width, uint32_t height);
 	void			move(uint32_t x, uint32_t y);
 
-	void			show_cursor();
-	void			hide_cursor();
+	void			show_cursor(bool show);
 
 	void			get_cursor_xy(int32_t& x, int32_t& y);
 	void			set_cursor_xy(int32_t x, int32_t y);

+ 51 - 5
engine/os/win/Thread.cpp

@@ -34,18 +34,52 @@ namespace os
 {
 
 //-----------------------------------------------------------------------------
-Thread::Thread(os::ThreadFunction f, LPVOID params, const char* name)
+Thread::Thread(const char* name) :
+	m_name(name),
+	m_is_running(false),
+	m_is_terminating(false)
 {
-	m_thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) f, params, 0, NULL);
+}
 
-	CE_ASSERT(m_thread != NULL, "Unable to create thread");
+//-----------------------------------------------------------------------------
+Thread::~Thread()
+{
+}
 
-	m_name = name;
+//-----------------------------------------------------------------------------
+bool Thread::is_running() const
+{
+	return m_is_running;
 }
 
 //-----------------------------------------------------------------------------
-Thread::~Thread()
+bool Thread::is_terminating() const
+{
+	return m_is_terminating;
+}
+
+//-----------------------------------------------------------------------------
+void Thread::start()
+{
+	m_is_terminating = false;
+
+	m_thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) Thread::background_proc, this, 0, NULL);
+
+	CE_ASSERT(m_thread != NULL, "Failed to create the thread '%s'", m_name);
+
+	m_is_running = true;
+}
+
+//-----------------------------------------------------------------------------
+void Thread::stop()
+{
+	m_is_terminating = true;
+}
+
+//-----------------------------------------------------------------------------
+int32_t	Thread::run()
 {
+	return 0;
 }
 
 //-----------------------------------------------------------------------------
@@ -62,5 +96,17 @@ void Thread::detach()
 	CE_ASSERT(closed, "Unable to close thread");
 }
 
+void* Thread::background_proc(void* thiz)
+{
+	Thread* thread  = (Thread*)thiz;
+
+	thread->run();
+
+	thread->m_is_running = false;
+
+	return NULL;
+}
+
+
 } // namespace os
 } // namespace crown

+ 19 - 2
engine/os/win/Thread.h

@@ -29,6 +29,7 @@ OTHER DEALINGS IN THE SOFTWARE.
 #include <windows.h>
 #include <process.h>
 #include <WinBase.h>
+
 #include "Types.h"
 #include "OS.h"
 
@@ -43,16 +44,32 @@ class Thread
 {
 public:
 
-					Thread(os::ThreadFunction f, LPVOID params, const char* name);
+					Thread(const char* name);
 					~Thread();
 
+	const char*		name() const;
+
 	void			join();
 	void			detach();
 
+	bool			is_running() const;
+	bool			is_terminating() const;
+
+	void			start();
+	void			stop();
+
+	virtual int32_t	run();
+
 private:
 
-	HANDLE			m_thread;
+	static void*	background_proc(void* thiz);
+
+private:
+	
 	const char*		m_name;
+	bool			m_is_running;
+	bool			m_is_terminating;
+	HANDLE			m_thread;
 };
 
 } // namespace os

+ 90 - 9
engine/os/win/WinOS.cpp

@@ -111,9 +111,12 @@ bool is_absolute_path(const char* path)
 
 	if (string::strlen(path) > 0)
 	{
-		if ((path[0] >= 65 && path[0] <= 90) || (path[0] >= 97 && path[0] <= 122))
+		if ((path[0] >= 'c' && path[0] <= 'z') || (path[0] >= 'C' && path[0] <= 'Z'))
 		{
-			return true;
+			if (path[1] == ':')
+			{
+				return true;
+			}
 		}
 	}
 
@@ -129,7 +132,7 @@ bool exists(const char* path)
 }
 
 //-----------------------------------------------------------------------------
-bool is_direcotry(const char* path)
+bool is_directory(const char* path)
 {
 	DWORD fileAttr;
 	fileAttr = GetFileAttributes(path);
@@ -139,7 +142,7 @@ bool is_direcotry(const char* path)
 //-----------------------------------------------------------------------------
 bool is_file(const char* path)
 {
-	return !is_dir(path);
+	return !is_directory(path);
 }
 
 //-----------------------------------------------------------------------------
@@ -207,11 +210,56 @@ const char* get_env(const char* env)
 }
 
 //-----------------------------------------------------------------------------
-// bool ls(const char* path, List<Str>& fileList)
-// {
-//	// TODO
-//	return false; 
-//}
+void list_files(const char* path, Vector<DynamicString>& files)
+{
+	HANDLE file = INVALID_HANDLE_VALUE;
+	WIN32_FIND_DATA ffd;
+
+	char cur_path[MAX_PATH_LENGTH];
+
+	string::strncpy(cur_path, path, string::strlen(path) + 1);
+	string::strncat(cur_path, "\\*", 2);
+
+	file = FindFirstFile(cur_path, &ffd);
+
+	do
+	{
+		CE_ASSERT(file != INVALID_HANDLE_VALUE, "Unable to list files. errono %d", GetLastError());
+
+		if ((string::strcmp(ffd.cFileName, ".") == 0) || (string::strcmp(ffd.cFileName, "..") == 0))
+		{
+			continue;
+		}
+	
+		DynamicString filename(default_allocator());
+
+		filename = ffd.cFileName;
+		files.push_back(filename);
+	}
+	while (FindNextFile(file, &ffd) != 0);
+
+	FindClose(file);
+}
+
+//-----------------------------------------------------------------------------
+const char* normalize_path(const char* path)
+{
+	static char norm[MAX_PATH_LENGTH];
+
+	for (uint32_t i = 0; i < string::strlen(path)+1; i++)
+	{
+		if (path[i] == '/')
+		{
+			norm[i] = '\\';
+		}
+		else
+		{
+			norm[i] = path[i];
+		}
+	}
+
+	return norm;
+}
 
 //-----------------------------------------------------------------------------
 void init_os()
@@ -271,5 +319,38 @@ void* lookup_symbol(void* library, const char* name)
 	return symbol;
 }
 
+//-----------------------------------------------------------------------------
+void execute_process(const char* args[])
+{
+	STARTUPINFO info;
+	memset(&info, 0, sizeof(info));
+	info.cb = sizeof(info);
+
+	PROCESS_INFORMATION process;
+	memset(&process, 0, sizeof(process));
+
+	DynamicString cmds(default_allocator());
+
+	for (uint32_t i = 0; args[i] != NULL; i++)
+	{
+		cmds += args[i];
+		cmds += ' ';
+	}
+
+	// Necessary because CreateProcess second argument must be non-const
+	char tmp[1024];
+	string::strncpy(tmp, normalize_path(cmds.c_str()), string::strlen(cmds.c_str()));
+
+	int32_t res;
+	if (res = CreateProcess(args[0], tmp, NULL, NULL, TRUE, 0, NULL, NULL, &info, &process))
+	{
+	    ::WaitForSingleObject(process.hProcess, INFINITE);
+   		CloseHandle(process.hProcess);
+    	CloseHandle(process.hThread);
+	}
+
+	CE_ASSERT(res != 0, "Unable to create process for %s, errno: %d\n", args[0], GetLastError());
+}
+
 } // namespace os
 } // namespace crown

+ 305 - 0
engine/os/win/inttypes.h

@@ -0,0 +1,305 @@
+// ISO C9x  compliant inttypes.h for Microsoft Visual Studio
+// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 
+// 
+//  Copyright (c) 2006 Alexander Chemeris
+// 
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+// 
+//   1. Redistributions of source code must retain the above copyright notice,
+//      this list of conditions and the following disclaimer.
+// 
+//   2. Redistributions in binary form must reproduce the above copyright
+//      notice, this list of conditions and the following disclaimer in the
+//      documentation and/or other materials provided with the distribution.
+// 
+//   3. The name of the author may be used to endorse or promote products
+//      derived from this software without specific prior written permission.
+// 
+// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// 
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef _MSC_VER // [
+#error "Use this header only with Microsoft Visual C++ compilers!"
+#endif // _MSC_VER ]
+
+#ifndef _MSC_INTTYPES_H_ // [
+#define _MSC_INTTYPES_H_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif
+
+#include "stdint.h"
+
+// 7.8 Format conversion of integer types
+
+typedef struct {
+   intmax_t quot;
+   intmax_t rem;
+} imaxdiv_t;
+
+// 7.8.1 Macros for format specifiers
+
+//#if !defined(__cplusplus) || defined(__STDC_FORMAT_MACROS) // [   See footnote 185 at page 198
+
+// The fprintf macros for signed integers are:
+#define PRId8       "d"
+#define PRIi8       "i"
+#define PRIdLEAST8  "d"
+#define PRIiLEAST8  "i"
+#define PRIdFAST8   "d"
+#define PRIiFAST8   "i"
+
+#define PRId16       "hd"
+#define PRIi16       "hi"
+#define PRIdLEAST16  "hd"
+#define PRIiLEAST16  "hi"
+#define PRIdFAST16   "hd"
+#define PRIiFAST16   "hi"
+
+#define PRId32       "I32d"
+#define PRIi32       "I32i"
+#define PRIdLEAST32  "I32d"
+#define PRIiLEAST32  "I32i"
+#define PRIdFAST32   "I32d"
+#define PRIiFAST32   "I32i"
+
+#define PRId64       "I64d"
+#define PRIi64       "I64i"
+#define PRIdLEAST64  "I64d"
+#define PRIiLEAST64  "I64i"
+#define PRIdFAST64   "I64d"
+#define PRIiFAST64   "I64i"
+
+#define PRIdMAX     "I64d"
+#define PRIiMAX     "I64i"
+
+#define PRIdPTR     "Id"
+#define PRIiPTR     "Ii"
+
+// The fprintf macros for unsigned integers are:
+#define PRIo8       "o"
+#define PRIu8       "u"
+#define PRIx8       "x"
+#define PRIX8       "X"
+#define PRIoLEAST8  "o"
+#define PRIuLEAST8  "u"
+#define PRIxLEAST8  "x"
+#define PRIXLEAST8  "X"
+#define PRIoFAST8   "o"
+#define PRIuFAST8   "u"
+#define PRIxFAST8   "x"
+#define PRIXFAST8   "X"
+
+#define PRIo16       "ho"
+#define PRIu16       "hu"
+#define PRIx16       "hx"
+#define PRIX16       "hX"
+#define PRIoLEAST16  "ho"
+#define PRIuLEAST16  "hu"
+#define PRIxLEAST16  "hx"
+#define PRIXLEAST16  "hX"
+#define PRIoFAST16   "ho"
+#define PRIuFAST16   "hu"
+#define PRIxFAST16   "hx"
+#define PRIXFAST16   "hX"
+
+#define PRIo32       "I32o"
+#define PRIu32       "I32u"
+#define PRIx32       "I32x"
+#define PRIX32       "I32X"
+#define PRIoLEAST32  "I32o"
+#define PRIuLEAST32  "I32u"
+#define PRIxLEAST32  "I32x"
+#define PRIXLEAST32  "I32X"
+#define PRIoFAST32   "I32o"
+#define PRIuFAST32   "I32u"
+#define PRIxFAST32   "I32x"
+#define PRIXFAST32   "I32X"
+
+#define PRIo64       "I64o"
+#define PRIu64       "I64u"
+#define PRIx64       "I64x"
+#define PRIX64       "I64X"
+#define PRIoLEAST64  "I64o"
+#define PRIuLEAST64  "I64u"
+#define PRIxLEAST64  "I64x"
+#define PRIXLEAST64  "I64X"
+#define PRIoFAST64   "I64o"
+#define PRIuFAST64   "I64u"
+#define PRIxFAST64   "I64x"
+#define PRIXFAST64   "I64X"
+
+#define PRIoMAX     "I64o"
+#define PRIuMAX     "I64u"
+#define PRIxMAX     "I64x"
+#define PRIXMAX     "I64X"
+
+#define PRIoPTR     "Io"
+#define PRIuPTR     "Iu"
+#define PRIxPTR     "Ix"
+#define PRIXPTR     "IX"
+
+// The fscanf macros for signed integers are:
+#define SCNd8       "d"
+#define SCNi8       "i"
+#define SCNdLEAST8  "d"
+#define SCNiLEAST8  "i"
+#define SCNdFAST8   "d"
+#define SCNiFAST8   "i"
+
+#define SCNd16       "hd"
+#define SCNi16       "hi"
+#define SCNdLEAST16  "hd"
+#define SCNiLEAST16  "hi"
+#define SCNdFAST16   "hd"
+#define SCNiFAST16   "hi"
+
+#define SCNd32       "ld"
+#define SCNi32       "li"
+#define SCNdLEAST32  "ld"
+#define SCNiLEAST32  "li"
+#define SCNdFAST32   "ld"
+#define SCNiFAST32   "li"
+
+#define SCNd64       "I64d"
+#define SCNi64       "I64i"
+#define SCNdLEAST64  "I64d"
+#define SCNiLEAST64  "I64i"
+#define SCNdFAST64   "I64d"
+#define SCNiFAST64   "I64i"
+
+#define SCNdMAX     "I64d"
+#define SCNiMAX     "I64i"
+
+#ifdef _WIN64 // [
+#  define SCNdPTR     "I64d"
+#  define SCNiPTR     "I64i"
+#else  // _WIN64 ][
+#  define SCNdPTR     "ld"
+#  define SCNiPTR     "li"
+#endif  // _WIN64 ]
+
+// The fscanf macros for unsigned integers are:
+#define SCNo8       "o"
+#define SCNu8       "u"
+#define SCNx8       "x"
+#define SCNX8       "X"
+#define SCNoLEAST8  "o"
+#define SCNuLEAST8  "u"
+#define SCNxLEAST8  "x"
+#define SCNXLEAST8  "X"
+#define SCNoFAST8   "o"
+#define SCNuFAST8   "u"
+#define SCNxFAST8   "x"
+#define SCNXFAST8   "X"
+
+#define SCNo16       "ho"
+#define SCNu16       "hu"
+#define SCNx16       "hx"
+#define SCNX16       "hX"
+#define SCNoLEAST16  "ho"
+#define SCNuLEAST16  "hu"
+#define SCNxLEAST16  "hx"
+#define SCNXLEAST16  "hX"
+#define SCNoFAST16   "ho"
+#define SCNuFAST16   "hu"
+#define SCNxFAST16   "hx"
+#define SCNXFAST16   "hX"
+
+#define SCNo32       "lo"
+#define SCNu32       "lu"
+#define SCNx32       "lx"
+#define SCNX32       "lX"
+#define SCNoLEAST32  "lo"
+#define SCNuLEAST32  "lu"
+#define SCNxLEAST32  "lx"
+#define SCNXLEAST32  "lX"
+#define SCNoFAST32   "lo"
+#define SCNuFAST32   "lu"
+#define SCNxFAST32   "lx"
+#define SCNXFAST32   "lX"
+
+#define SCNo64       "I64o"
+#define SCNu64       "I64u"
+#define SCNx64       "I64x"
+#define SCNX64       "I64X"
+#define SCNoLEAST64  "I64o"
+#define SCNuLEAST64  "I64u"
+#define SCNxLEAST64  "I64x"
+#define SCNXLEAST64  "I64X"
+#define SCNoFAST64   "I64o"
+#define SCNuFAST64   "I64u"
+#define SCNxFAST64   "I64x"
+#define SCNXFAST64   "I64X"
+
+#define SCNoMAX     "I64o"
+#define SCNuMAX     "I64u"
+#define SCNxMAX     "I64x"
+#define SCNXMAX     "I64X"
+
+#ifdef _WIN64 // [
+#  define SCNoPTR     "I64o"
+#  define SCNuPTR     "I64u"
+#  define SCNxPTR     "I64x"
+#  define SCNXPTR     "I64X"
+#else  // _WIN64 ][
+#  define SCNoPTR     "lo"
+#  define SCNuPTR     "lu"
+#  define SCNxPTR     "lx"
+#  define SCNXPTR     "lX"
+#endif  // _WIN64 ]
+
+//#endif // __STDC_FORMAT_MACROS ]
+
+// 7.8.2 Functions for greatest-width integer types
+
+// 7.8.2.1 The imaxabs function
+#define imaxabs _abs64
+
+// 7.8.2.2 The imaxdiv function
+
+// This is modified version of div() function from Microsoft's div.c found
+// in %MSVC.NET%\crt\src\div.c
+#ifdef STATIC_IMAXDIV // [
+static
+#else // STATIC_IMAXDIV ][
+_inline
+#endif // STATIC_IMAXDIV ]
+imaxdiv_t __cdecl imaxdiv(intmax_t numer, intmax_t denom)
+{
+   imaxdiv_t result;
+
+   result.quot = numer / denom;
+   result.rem = numer % denom;
+
+   if (numer < 0 && result.rem > 0) {
+      // did division wrong; must fix up
+      ++result.quot;
+      result.rem -= denom;
+   }
+
+   return result;
+}
+
+// 7.8.2.3 The strtoimax and strtoumax functions
+#define strtoimax _strtoi64
+#define strtoumax _strtoui64
+
+// 7.8.2.4 The wcstoimax and wcstoumax functions
+#define wcstoimax _wcstoi64
+#define wcstoumax _wcstoui64
+
+
+#endif // _MSC_INTTYPES_H_ ]

+ 98 - 0
engine/renderers/CommandBuffer.h

@@ -0,0 +1,98 @@
+/*
+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 "Assert.h"
+#include "RendererTypes.h"
+
+namespace crown
+{
+
+#define MAX_COMMAND_BUFFER_SIZE 1024 * 1024
+
+class CommandBuffer
+{
+public:
+
+	//-----------------------------------------------------------------------------
+	CommandBuffer() : m_size(0)
+	{
+		// Ensure at least a command is in queue
+		commit();
+	}
+
+	//-----------------------------------------------------------------------------
+	void clear()
+	{
+		m_size = 0;
+	}
+
+	//-----------------------------------------------------------------------------
+	template<typename T>
+	void write(const T type)
+	{
+		write((void*)&type, sizeof(T));
+	}
+
+	template<typename T>
+	void read(T& data)
+	{
+		read((void*)&data, sizeof(T));
+	}
+
+	//-----------------------------------------------------------------------------
+	void write(const void* data, size_t size)
+	{
+		CE_ASSERT(m_size + size < MAX_COMMAND_BUFFER_SIZE, "Command buffer overflow");
+
+		memcpy(&m_buffer[m_size], data, size);
+		m_size += size;
+	}
+
+	//-----------------------------------------------------------------------------
+	void read(void* data, size_t size)
+	{
+		CE_ASSERT(m_size + size < MAX_COMMAND_BUFFER_SIZE, "Command buffer overflow");
+		
+		memcpy(data, &m_buffer[m_size], size);
+		m_size += size;
+	}
+
+	//-----------------------------------------------------------------------------
+	void commit()
+	{
+		write(COMMAND_END);
+		m_size = 0;
+	}
+
+public:
+
+	size_t	m_size;
+	char	m_buffer[MAX_COMMAND_BUFFER_SIZE];
+};
+
+} // namespace crown

+ 114 - 0
engine/renderers/ConstantBuffer.h

@@ -0,0 +1,114 @@
+/*
+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 "Assert.h"
+#include "RendererTypes.h"
+
+namespace crown
+{
+
+extern const size_t UNIFORM_SIZE_TABLE[UNIFORM_END];
+
+#define MAX_CONSTANT_BUFFER_SIZE 1024 * 1024
+
+class ConstantBuffer
+{
+public:
+
+	ConstantBuffer()
+		: m_size(0)
+	{
+		commit();
+	}
+
+	void clear()
+	{
+		m_size = 0;
+	}
+
+	void write(uint32_t data)
+	{
+		write(&data, sizeof(uint32_t));
+	}
+
+	uint32_t read()
+	{
+		uint32_t data;
+		read(&data, sizeof(uint32_t));
+		return data;
+	}
+
+	const void* read(size_t size)
+	{
+		CE_ASSERT(m_size + size < MAX_CONSTANT_BUFFER_SIZE, "Constant buffer overflow");
+
+		const void* data = (void*) &m_buffer[m_size];
+		m_size += size;
+
+		return data;
+	}
+
+	void write(const void* data, size_t size)
+	{
+		CE_ASSERT(m_size + size < MAX_CONSTANT_BUFFER_SIZE, "Constant buffer overflow");
+
+		memcpy(&m_buffer[m_size], data, size);
+		m_size += size;
+	}
+
+	void read(void* data, size_t size)
+	{
+		CE_ASSERT(m_size + size < MAX_CONSTANT_BUFFER_SIZE, "Constant buffer overflow");
+
+		memcpy(data, &m_buffer[m_size], size);
+		m_size += size;		
+	}
+
+	void write_constant(UniformId id, UniformType type, void* data, uint8_t num)
+	{
+		size_t size = UNIFORM_SIZE_TABLE[type] * num;
+
+		write(type);
+		write(&id, sizeof(UniformId));
+		write(&size, sizeof(size_t));
+		write(data, size);
+	}
+
+	void commit()
+	{
+		write(UNIFORM_END);
+		m_size = 0;
+	}
+
+private:
+
+	size_t m_size;
+	char m_buffer[MAX_CONSTANT_BUFFER_SIZE];
+};
+
+} // namespace crown

+ 1 - 1
engine/renderers/DebugRenderer.cpp

@@ -140,7 +140,7 @@ void DebugRenderer::draw_all()
 {
 	if (m_lines_count > 0)
 	{
-		m_renderer.draw_lines(m_lines[0].to_float_ptr(), m_colors[0].to_float_ptr(), m_lines_count * 2);
+		// m_renderer.draw_lines(m_lines[0].to_float_ptr(), m_colors[0].to_float_ptr(), m_lines_count * 2);
 	}
 
 	m_lines_count = 0;

+ 0 - 105
engine/renderers/Material.h

@@ -1,105 +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.
-*/
-
-#pragma once
-
-namespace crown
-{
-
-enum FogMode
-{
-	FM_LINEAR	= 0,
-	FM_EXP		= 1,
-	FM_EXP2		= 2,
-	FM_COUNT
-};
-
-enum CompareFunction
-{
-	CF_NEVER	= 0,
-	CF_LESS		= 1,
-	CF_EQUAL	= 2,
-	CF_LEQUAL	= 3,
-	CF_GREATER	= 4,
-	CF_NOTEQUAL	= 5,
-	CF_GEQUAL	= 6,
-	CF_ALWAYS	= 7,
-	CF_COUNT
-};
-
-enum ShadingType
-{
-	ST_FLAT		= 0,
-	ST_SMOOTH	= 1,
-	ST_COUNT
-};
-
-enum PolygonMode
-{
-	PM_POINT	= 0,
-	PM_LINE		= 1,
-	PM_FILL		= 2,
-	PM_COUNT
-};
-
-enum FrontFace
-{
-	FF_CW		= 0,
-	FF_CCW		= 1,
-	FF_COUNT
-};
-
-enum BlendEquation
-{
-	BE_FUNC_ADD					= 0,
-	BE_FUNC_SUBTRACT			= 1,
-	BE_FUNC_REVERSE_SUBTRACT	= 2,
-	BE_MIN						= 3,
-	BE_MAX						= 4,
-	BE_COUNT
-};
-
-enum BlendFunction
-{
-	BF_ZERO						= 0,
-	BF_ONE						= 1,
-	BF_SRC_COLOR				= 2,
-	BF_ONE_MINUS_SRC_COLOR		= 3,
-	BF_DST_COLOR				= 4,
-	BF_ONE_MINUS_DST_COLOR		= 5,
-	BF_SRC_ALPHA				= 6,
-	BF_ONE_MINUS_SRC_ALPHA		= 7,
-	BF_DST_ALPHA				= 8,
-	BF_ONE_MINUS_DST_ALPHA		= 9,
-	BF_CONSTANT_COLOR			= 10,
-	BF_ONE_MINUS_CONSTANT_COLOR	= 11,
-	BF_CONSTANT_ALPHA			= 12,
-	BF_ONE_MINUS_CONSTANT_ALPHA	= 13,
-	BF_SRC_ALPHA_SATURATE		= 14,
-	BF_COUNT
-};
-
-} // namespace crown

+ 0 - 117
engine/renderers/PixelFormat.cpp

@@ -1,117 +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 "Types.h"
-#include "PixelFormat.h"
-
-namespace crown
-{
-
-//-----------------------------------------------------------------------------
-size_t Pixel::bits_per_pixel(PixelFormat format)
-{
-	return bytes_per_pixel(format) * 8;
-}
-
-//-----------------------------------------------------------------------------
-size_t Pixel::bytes_per_pixel(PixelFormat format)
-{
-	switch (format)
-	{
-		case PF_L_8:
-		case PF_RGB_3_3_2:
-		case PF_BGR_2_3_3:
-		{
-			return 1;
-		}
-		case PF_L_16:
-		case PF_LA_8:
-		case PF_AL_8:
-		case PF_RGB_5_6_5:
-		case PF_BGR_5_6_5:
-		case PF_RGBA_4_4_4_4:
-		case PF_RGBA_5_5_5_1:
-		case PF_ABGR_4_4_4_4:
-		case PF_ABGR_1_5_5_5:
-		{
-			return 2;
-		}
-		case PF_RGB_8:
-		case PF_BGR_8:
-		{
-			return 3;
-		}
-		case PF_L_32:
-		case PF_L_FLOAT_32:
-		case PF_LA_16:
-		case PF_AL_16:
-		case PF_RGBA_8:
-		case PF_RGBA_8_8_8_8:
-		case PF_RGBA_10_10_10_2:
-		case PF_ABGR_8:
-		case PF_ABGR_8_8_8_8:
-		case PF_ABGR_2_10_10_10:
-		{
-			return 4;
-		}
-		case PF_RGB_16:
-		case PF_BGR_16:
-		{
-			return 6;
-		}
-		case PF_LA_32:
-		case PF_LA_FLOAT_32:
-		case PF_AL_32:
-		case PF_AL_FLOAT_32:
-		case PF_RGBA_16:
-		case PF_ABGR_16:
-		{
-			return 8;
-		}
-		case PF_RGB_32:
-		case PF_RGB_FLOAT_32:
-		case PF_BGR_32:
-		case PF_BGR_FLOAT_32:
-		{
-			return 12;
-		}
-		case PF_RGBA_32:
-		case PF_RGBA_FLOAT_32:
-		case PF_ABGR_32:
-		case PF_ABGR_FLOAT_32:
-		{
-			return 16;
-		}
-		case PF_UNKNOWN:
-		default:
-		{
-			return 0;
-		}
-	}
-}
-
-} // namespace crown
-

+ 24 - 70
engine/renderers/PixelFormat.h

@@ -27,87 +27,41 @@ OTHER DEALINGS IN THE SOFTWARE.
 #pragma once
 
 #include "Types.h"
+#include "RendererTypes.h"
 
 namespace crown
 {
 
-// [0 - 2]		-> 8-bit
-// [3 - 11] 	-> 16-bit
-// [12 - 13]	-> 24-bit
-// [14 - 23]	-> 32-bit
-// [24 - 25]	-> 48-bit
-// [26 - 31]	-> 64-bit
-// [32 - 35]	-> 96-bit
-// [36 - 39]	-> 128-bit
-// 40			-> Unknown (0-bit)
-
-
-/// Enumerates pixel formats.
-enum PixelFormat
-{
-	PF_L_8 = 0,				///< Luminance only, 8-bit
-	PF_L_16 = 3,			///< Luminance only, 16-bit
-	PF_L_32 = 14,			///< Luminance only, 32-bit integer
-	PF_L_FLOAT_32 = 15,		///< Luminance only, 32-bit flaoting point
-
-	PF_LA_8 = 4,			///< Luminance and alpha, 8-bit each
-	PF_LA_16 = 16,			///< Luminance and alpha, 16-bit each
-	PF_LA_32 = 26,			///< Luminance and alpha, 32-bit integer each
-	PF_LA_FLOAT_32 = 27,	///< Luminance and alpha, 32-bit floating point each
-
-	PF_AL_8 = 5,			///< Luminance and alpha, 8-bit each
-	PF_AL_16 = 17,			///< Luminance and alpha, 16-bit each
-	PF_AL_32 = 28,			///< Luminance and alpha, 32-bit integer each
-	PF_AL_FLOAT_32 = 29,	///< Luminance and alpha, 32-bit floating point each
-
-	PF_RGB_8 = 12,			///< RGB values, 8-bit each
-	PF_RGB_16 = 24,			///< RGB values, 16-bit each
-	PF_RGB_32 = 32,			///< RGB values, 32-bit integer each
-	PF_RGB_FLOAT_32 = 33,	///< RGB values, 32-bit floating point each
-
-	PF_RGB_3_3_2 = 1,		///< Packed 8-bit RGB values
-	PF_RGB_5_6_5 = 6,		///< Packed 16-bit RGB values
-
-	PF_BGR_8 = 13,			///< BGR values, 8-bit each
-	PF_BGR_16 = 25,			///< BGR values, 16-bit each
-	PF_BGR_32 = 34,			///< BGR values, 32-bit integer each
-	PF_BGR_FLOAT_32 = 35,	///< BGR values, 32-bit floating point each
-
-	PF_BGR_2_3_3 = 2,		///< Packed 8-bit BGR values
-	PF_BGR_5_6_5 = 7,		///< Packed 16-bit BGR values
-
-	PF_RGBA_8 = 18,			///< RGBA values, 8-bit each
-	PF_RGBA_16 = 30,		///< RGBA values, 16-bit each
-	PF_RGBA_32 = 36,		///< RGBA values, 32-bit integer each
-	PF_RGBA_FLOAT_32 = 37,	///< RGBA values, 32-bit floating point each
-
-	PF_RGBA_4_4_4_4 = 8,	///< Packed 16-bit RGBA values
-	PF_RGBA_5_5_5_1 = 9,	///< Packed 16-bit RGBA values
-	PF_RGBA_8_8_8_8 = 19,	///< Packed 32-bit RGBA values
-	PF_RGBA_10_10_10_2 = 20,///< Packed 32-bit RGBA values
-
-	PF_ABGR_8 = 21,			///< ABGR values, 8-bit each
-	PF_ABGR_16 = 31,		///< ABGR values, 16-bit each
-	PF_ABGR_32 = 38,		///< ABGR values, 32-bit integer each
-	PF_ABGR_FLOAT_32 = 39,	///< ABGR values, 32-bit floating point each
-
-	PF_ABGR_4_4_4_4 = 10,	///< Packed 16-bit ABGR values
-	PF_ABGR_1_5_5_5 = 11,	///< Packed 16-bit ABGR values
-	PF_ABGR_8_8_8_8 = 22,	///< Packed 32-bit ABGR values
-	PF_ABGR_2_10_10_10 = 23,///< Packed 32-bit ABGR values
-
-	PF_UNKNOWN = 40
-};
-
 class Pixel
 {
 public:
 
 	/// Returns the bytes occupied by @a format
-	static size_t bytes_per_pixel(PixelFormat format);
+	static size_t bytes_per_pixel(PixelFormat format)
+	{
+		switch (format)
+		{
+			case PIXEL_RGB_8:
+			{
+				return 3;
+			}
+			case PIXEL_RGBA_8:
+			{
+				return 4;
+			}
+			default:
+			{
+				CE_ASSERT(false, "Oops, unknown pixel format");
+				return 0;
+			}
+		}
+	}
 
 	/// Returns the bits occupied by @a format
-	static size_t bits_per_pixel(PixelFormat format);
+	static size_t bits_per_pixel(PixelFormat format)
+	{
+		return bytes_per_pixel(format) * 8;
+	}
 
 private:
 

+ 0 - 33
engine/renderers/PixelShader.h

@@ -1,33 +0,0 @@
-/*
-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
-
-namespace crown
-{
-
-const uint32_t MAX_PIXEL_SHADERS = 128;
-
-} // namespace crown

+ 327 - 0
engine/renderers/RenderContext.h

@@ -0,0 +1,327 @@
+/*
+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 "Color4.h"
+#include "Mat4.h"
+#include "IdTable.h"
+#include "CommandBuffer.h"
+#include "ConstantBuffer.h"
+#include "RendererTypes.h"
+
+namespace crown
+{
+
+#define MAX_RENDER_LAYERS			32
+#define MAX_RENDER_STATES			1024
+
+// State flags
+#define STATE_NONE					0x0000000000000000
+
+#define STATE_DEPTH_WRITE			0x0000000000000001
+#define STATE_COLOR_WRITE			0x0000000000000002
+#define STATE_ALPHA_WRITE			0x0000000000000004
+
+#define STATE_CULL_CW				0x0000000000000010
+#define STATE_CULL_CCW				0x0000000000000020
+
+#define STATE_TEXTURE_0				0x0000000000000100
+#define STATE_TEXTURE_1				0x0000000000000200
+#define STATE_TEXTURE_2				0x0000000000000400
+#define STATE_TEXTURE_3				0x0000000000000800
+#define STATE_TEXTURE_MASK			0x0000000000000F00
+#define STATE_MAX_TEXTURES			4
+
+#define STATE_PRIMITIVE_TRIANGLES	0x0000000000000000
+#define STATE_PRIMITIVE_POINTS		0x0000000000001000
+#define STATE_PRIMITIVE_LINES		0x0000000000002000
+#define STATE_PRIMITIVE_MASK		0x000000000000f000
+#define STATE_PRIMITIVE_SHIFT		12
+
+#define CLEAR_COLOR					0x1
+#define CLEAR_DEPTH					0x2
+
+// Texture flags
+#define TEXTURE_FILTER_NEAREST		0x00000001
+#define TEXTURE_FILTER_LINEAR		0x00000002
+#define TEXTURE_FILTER_BILINEAR		0x00000003
+#define TEXTURE_FILTER_TRILINEAR	0x00000004
+#define TEXTURE_FILTER_MASK			0x0000000F
+#define TEXTURE_FILTER_SHIFT		0
+
+#define TEXTURE_WRAP_CLAMP_EDGE		0x00000010
+#define TEXTURE_WRAP_CLAMP_REPEAT	0x00000020
+#define TEXTURE_WRAP_MASK			0x000000F0
+#define TEXTURE_WRAP_SHIFT			4
+
+// Sampler flags
+#define SAMPLER_TEXTURE				0x10000000
+#define SAMPLER_MASK				0xF0000000
+#define SAMPLER_SHIFT				28
+
+struct ViewRect
+{
+	void clear()
+	{
+		m_x = 0;
+		m_y = 0;
+		m_width = 0;
+		m_height = 0;
+	}
+
+	uint32_t area() const
+	{
+		return (m_width - m_x) * (m_height - m_y);
+	}
+
+	uint16_t m_x;
+	uint16_t m_y;
+	uint16_t m_width;
+	uint16_t m_height;
+};
+
+struct ClearState
+{
+	void clear()
+	{
+		m_color = Color4::GRAY;
+		m_depth = 1.0f;
+	}
+
+public:
+
+	uint8_t		m_flags;
+	Color4		m_color;
+	float		m_depth;
+};
+
+struct Sampler
+{
+	Id			sampler_id;
+	uint32_t	flags;
+};
+
+struct RenderState
+{
+	void clear()
+	{
+		m_flags = STATE_NONE;
+
+		pose = Mat4::IDENTITY;
+		program.id = INVALID_ID;
+		vb.id = INVALID_ID;
+		ib.id = INVALID_ID;
+
+		for (uint32_t i = 0; i < STATE_MAX_TEXTURES; i++)
+		{
+			samplers[i].sampler_id.id = INVALID_ID;
+			samplers[i].flags = SAMPLER_TEXTURE;
+		}
+	}
+
+public:
+
+	uint64_t		m_flags;
+
+	Mat4			pose;
+	GPUProgramId	program;
+	VertexBufferId	vb;
+	IndexBufferId	ib;
+	Sampler			samplers[STATE_MAX_TEXTURES];
+};
+
+struct RenderKey
+{
+	void clear()
+	{
+		m_layer = 0;
+	}
+
+	uint64_t encode()
+	{
+		return uint64_t(m_layer) << 56;
+	}
+
+	void decode(uint64_t key)
+	{
+		m_layer = (key >> 56) & 0xFF;
+	}
+
+public:
+
+	uint8_t m_layer;
+};
+
+struct RenderContext
+{
+	RenderContext()
+	{
+		clear();
+	}
+
+	void set_state(uint64_t flags)
+	{
+		m_state.m_flags = flags;
+	}
+
+	void set_pose(const Mat4& pose)
+	{
+		m_state.pose = pose;
+	}
+
+	void set_program(GPUProgramId program)
+	{
+		m_state.program = program;
+	}
+
+	void set_vertex_buffer(VertexBufferId vb)
+	{
+		m_state.vb = vb;
+	}
+
+	void set_index_buffer(IndexBufferId ib)
+	{
+		m_state.ib = ib;
+	}
+
+	void set_uniform(UniformId id, UniformType type, void* value, uint8_t num)
+	{
+		m_constants.write_constant(id, type, value, num);
+	}
+
+	void set_texture(uint8_t unit, UniformId sampler_uniform, TextureId texture, uint32_t flags)
+	{
+		m_flags |= STATE_TEXTURE_0 << unit;
+
+		Sampler& sampler = m_state.samplers[unit];
+		sampler.sampler_id = texture;
+		sampler.flags |= SAMPLER_TEXTURE | flags;
+
+		set_uniform(sampler_uniform, UNIFORM_INTEGER_1, &unit, 1);
+	}
+
+	void set_layer_render_target(uint8_t layer, RenderTargetId target)
+	{
+		CE_ASSERT(layer < MAX_RENDER_LAYERS, "Layer out of bounds");
+
+		m_targets[layer] = target;
+	}
+
+	void set_layer_clear(uint8_t layer, uint8_t flags, const Color4& color, float depth)
+	{
+		CE_ASSERT(layer < MAX_RENDER_LAYERS, "Layer out of bounds");
+
+		m_clears[layer].m_flags = flags;
+		m_clears[layer].m_color = color;
+		m_clears[layer].m_depth = depth;
+	}
+
+	void set_layer_view(uint8_t layer, const Mat4& view)
+	{
+		CE_ASSERT(layer < MAX_RENDER_LAYERS, "Layer out of bounds");
+
+		m_view_matrices[layer] = view;
+	}
+
+	void set_layer_projection(uint8_t layer, const Mat4& projection)
+	{
+		CE_ASSERT(layer < MAX_RENDER_LAYERS, "Layer out of bounds");
+
+		m_projection_matrices[layer] = projection;
+	}
+
+	void set_layer_viewport(uint8_t layer, uint16_t x, uint16_t y, uint16_t width, uint16_t height)
+	{
+		CE_ASSERT(layer < MAX_RENDER_LAYERS, "Layer out of bounds");
+
+		m_viewports[layer].m_x = x;
+		m_viewports[layer].m_y = y;
+		m_viewports[layer].m_width = width;
+		m_viewports[layer].m_height = height;
+	}
+
+	void set_layer_scissor(uint8_t layer, uint16_t x, uint16_t y, uint16_t width, uint16_t height)
+	{
+		CE_ASSERT(layer < MAX_RENDER_LAYERS, "Layer out of bounds");
+
+		m_scissors[layer].m_x = x;
+		m_scissors[layer].m_y = y;
+		m_scissors[layer].m_width = width;
+		m_scissors[layer].m_height = height;
+	}
+
+	void commit(uint8_t layer)
+	{
+		m_render_key.m_layer = layer;
+
+		m_states[m_num_states] = m_state;
+		m_keys[m_num_states] = m_render_key.encode();
+		m_num_states++;
+
+		m_render_key.clear();
+		m_state.clear();
+	}
+
+	void clear()
+	{
+		m_flags = STATE_NONE;
+		m_render_key.clear();
+
+		m_num_states = 0;
+		m_state.clear();
+	}
+
+	void push()
+	{
+		m_commands.commit();
+		m_constants.commit();
+	}
+
+public:
+
+	uint64_t m_flags;
+	RenderKey m_render_key;
+	RenderState m_state;
+
+	// Per-state data
+	uint32_t m_num_states;
+	RenderState m_states[MAX_RENDER_STATES];
+	ClearState m_clears[MAX_RENDER_STATES];
+	uint64_t m_keys[MAX_RENDER_STATES];
+
+	// Per-layer data
+	RenderTargetId m_targets[MAX_RENDER_LAYERS];
+	Mat4 m_view_matrices[MAX_RENDER_LAYERS];
+	Mat4 m_projection_matrices[MAX_RENDER_LAYERS];
+	ViewRect m_viewports[MAX_RENDER_LAYERS];
+	ViewRect m_scissors[MAX_RENDER_LAYERS];
+
+	CommandBuffer m_commands;
+	ConstantBuffer m_constants;
+};
+
+} // namespace crown

+ 645 - 168
engine/renderers/Renderer.h

@@ -28,206 +28,683 @@ OTHER DEALINGS IN THE SOFTWARE.
 
 #include "Config.h"
 #include "Types.h"
-#include "Color4.h"
-#include "Mat4.h"
-#include "VertexBuffer.h"
-#include "IndexBuffer.h"
-#include "RenderBuffer.h"
-#include "Texture.h"
-#include "Material.h"
 #include "PixelFormat.h"
 #include "VertexFormat.h"
-#include "IdTable.h"
+#include "StringUtils.h"
+#include "RenderContext.h"
+#include "Thread.h"
+#include "OS.h"
 
 namespace crown
 {
 
-enum MatrixType
-{
-	MT_VIEW			= 0,
-	MT_MODEL		= 1,
-	MT_PROJECTION	= 2,
-	MT_TEXTURE		= 3,
-	MT_COLOR		= 4,
-	MT_COUNT
-};
-
-enum LightType
-{
-	LT_POINT		= 0,
-	LT_DIRECTION	= 1,
-	LT_SPOT			= 2
-};
-
-enum ShaderAttrib
-{
-	SA_VERTEX			= 0,
-	SA_COORDS			= 1,
-	SA_NORMAL			= 2,
-	SA_DIFFUSE_MAP		= 3,
-	SA_DETAIL_MAP		= 4,
-	SA_NORMAL_MAP		= 5,
-
-	SA_COUNT
-};
-
-// Keep in sync with ShaderAttrib
-const char* const SHADER_ATTRIB_NAMES[] =
-{
-	"vertex",			// 0
-	"coords",			// 1
-	"normal",			// 2
-	"diffuse_map",		// 3
-	"detail_map",		// 4
-	"normal_map"		// 5
-};
-
-typedef Id VertexBufferId;
-typedef Id IndexBufferId;
-typedef Id RenderBufferId;
-typedef Id TextureId;
-typedef Id VertexShaderId;
-typedef Id PixelShaderId;
-typedef Id GPUProgramId;
-
-class VertexBuffer;
-class IndexBuffer;
-class Vec2;
-class Vec3;
-class Vec4;
-class Mat4;
+extern ShaderUniform name_to_stock_uniform(const char* uniform);
+class RendererImplementation;
 
 class Renderer
 {
 public:
 
-	static Renderer*		create(Allocator& a);
-	static void				destroy(Allocator& a, Renderer* renderer);
-
-	virtual 				~Renderer() {};
-
-	virtual void			init() = 0;
-	virtual void			shutdown() = 0;
-
-	/// Creates a new vertex buffer optimized for rendering static vertex data.
-	/// @a vertices is the array containig @a count vertex data elements of the given @a format.
-	virtual VertexBufferId	create_vertex_buffer(size_t count, VertexFormat format, const void* vertices) = 0;
-
-	/// Creates a new vertex buffer optimized for rendering dynamic vertex data.
-	/// @a vertices is the array containig @a count vertex data elements of the given @a format.
-	virtual VertexBufferId	create_dynamic_vertex_buffer(size_t count, VertexFormat format, const void* vertices) = 0;
-
-	/// Updates the data associated with the given vertex buffer @a id.
-	/// @a vertices is the array containig @a count vertex data elements of the format
-	/// specified at the creation of the buffer.
-	/// @note
-	/// @a count and @a offset together do not have to exceed the number of elements specified
-	/// at the creation of the buffer.	
-	virtual void			update_vertex_buffer(VertexBufferId id, size_t offset, size_t count, const void* vertices) = 0;
-
-	/// Destroys the @a id vertex buffer.
-	virtual void			destroy_vertex_buffer(VertexBufferId id) = 0;
-
-	/// Creates a new index buffer optimized for rendering static index buffers.
-	/// @a indices is the array containing @a count index data elements.
-	virtual IndexBufferId	create_index_buffer(size_t count, const void* indices) = 0;
-
-	/// Destroys the @a id index buffer.
-	virtual void			destroy_index_buffer(IndexBufferId id) = 0;
-
-	virtual TextureId		create_texture(uint32_t width, uint32_t height, PixelFormat format, const void* data) = 0;
-	virtual void			update_texture(TextureId id, uint32_t x, uint32_t y, uint32_t width, uint32_t height, const void* data) = 0;
-	virtual void			destroy_texture(TextureId id) = 0;
-
-	virtual VertexShaderId	create_vertex_shader(const char* program) = 0;
-	virtual void			destroy_vertex_shader(VertexShaderId id) = 0;
+	Renderer(Allocator& a);
+	~Renderer();
 
-	virtual PixelShaderId 	create_pixel_shader(const char* program) = 0;
-	virtual void			destroy_pixel_shader(PixelShaderId id) = 0;
+	void init_impl();
+	void shutdown_impl();
+	void render_impl();
 
-	virtual GPUProgramId	create_gpu_program(VertexShaderId vs, PixelShaderId ps) = 0;
-	virtual void			destroy_gpu_program(GPUProgramId id) = 0;
+	void create_vertex_buffer_impl(VertexBufferId id, size_t count, VertexFormat format, const void* vertices);
+	void create_dynamic_vertex_buffer_impl(VertexBufferId id, size_t count, VertexFormat format);
+	void update_vertex_buffer_impl(VertexBufferId id, size_t offset, size_t count, const void* vertices);
+	void destroy_vertex_buffer_impl(VertexBufferId id);
 
-	virtual void			set_gpu_program_bool_uniform(GPUProgramId id, const char* name, bool value) = 0;
-	virtual void			set_gpu_program_int_uniform(GPUProgramId id, const char* name, int value) = 0;
+	void create_index_buffer_impl(IndexBufferId id, size_t count, const void* indices);
+	void create_dynamic_index_buffer_impl(IndexBufferId id, size_t count);
+	void update_index_buffer_impl(IndexBufferId id, size_t offset, size_t count, const void* indices);
+	void destroy_index_buffer_impl(IndexBufferId id);
 
-	virtual void			set_gpu_program_vec2_uniform(GPUProgramId id, const char* name, const Vec2& value) = 0;
-	virtual void			set_gpu_program_vec3_uniform(GPUProgramId id, const char* name, const Vec3& value) = 0;
-	virtual void			set_gpu_program_vec4_uniform(GPUProgramId id, const char* name, const Vec4& value) = 0;
+	void create_texture_impl(TextureId id, uint32_t width, uint32_t height, PixelFormat format, const void* data);
+	void update_texture_impl(TextureId id, uint32_t x, uint32_t y, uint32_t width, uint32_t height, const void* data);
+	void destroy_texture_impl(TextureId id);
 
-	virtual void			set_gpu_porgram_mat3_uniform(GPUProgramId id, const char* name, const Mat3& value) = 0;
-	virtual void			set_gpu_program_mat4_uniform(GPUProgramId id, const char* name, const Mat4& value) = 0;
+	void create_shader_impl(ShaderId id, ShaderType type, const char* text);
+	void destroy_shader_impl(ShaderId id);
 
-	virtual void			set_gpu_program_sampler_uniform(GPUProgramId id, const char* name, uint32_t value) = 0;
+	void create_gpu_program_impl(GPUProgramId id, ShaderId vertex, ShaderId pixel);
+	void destroy_gpu_program_impl(GPUProgramId id);
 
-	virtual void			bind_gpu_program(GPUProgramId id) const = 0;
+	void create_uniform_impl(UniformId id, const char* name, UniformType type, uint8_t num);
+	void update_uniform_impl(UniformId id, size_t size, const void* data);
+	void destroy_uniform_impl(UniformId id);
 
-	//virtual RenderBufferId	create_render_buffer(uint32_t width, uint32_t height, PixelFormat format) = 0;
-	//virtual void			destroy_render_buffer(RenderBufferId id) = 0;
+	void create_render_target_impl(RenderTargetId id, uint16_t width, uint16_t height, RenderTargetFormat format);
+	void destroy_render_target_impl(RenderTargetId id);
 
-	///	Tasks to perform before a frame is rendered.
-	virtual void			frame() = 0;
+	inline void init()
+	{
+		m_should_run = true;
+		m_thread.start(render_thread, this);
 
-	/// Sets the clearing color of the framebuffer.
-	virtual void			set_clear_color(const Color4& color) = 0;
+		m_submit->m_commands.write(COMMAND_INIT_RENDERER);
+		frame();
+	}
 
-	/// Sets the global ambient light @a color.
-	virtual void			set_ambient_light(const Color4& color) = 0;
+	inline void shutdown()
+	{
+		if (m_should_run)
+		{
+			m_submit->m_commands.write(COMMAND_SHUTDOWN_RENDERER);
+			frame();
 
-	//! Sets the texture to use in the specified layer
-	virtual void			bind_texture(uint32_t layer, TextureId texture) = 0;
+			m_should_run = false;
+			m_thread.stop();		
+		}
+	}
 
-	/// Set whether the given texture @a unit is enabled.
-	virtual void			set_texturing(uint32_t unit, bool texturing) = 0;
+	/// Creates a new vertex buffer optimized for rendering static vertex data.
+	/// @a vertices is the array containig @a count vertex data elements of the given @a format.
+	inline VertexBufferId create_vertex_buffer(size_t count, VertexFormat format, const void* vertices)
+	{
+		const VertexBufferId id = m_vertex_buffers.create();
 
-	/// Sets the texture @a wrap parameter for the given texture @a unit.
-	virtual void			set_texture_wrap(uint32_t unit, TextureWrap wrap) = 0;
+		m_submit->m_commands.write(COMMAND_CREATE_VERTEX_BUFFER);
+		m_submit->m_commands.write(id);
+		m_submit->m_commands.write(count);
+		m_submit->m_commands.write(format);
+		m_submit->m_commands.write(vertices);
 
-	/// Sets the @a filter for the given texture @a unit.
-	virtual void			set_texture_filter(uint32_t unit, TextureFilter filter) = 0;
+		return id;
+	}
 
-	/// Sets whether backface-culling is enabled.
-	virtual void			set_backface_culling(bool culling) = 0;
+	inline VertexBufferId create_dynamic_vertex_buffer(size_t count, VertexFormat format)
+	{
+		const VertexBufferId id = m_vertex_buffers.create();
 
-	/// Sets whether depth test is enabled.
-	virtual void			set_depth_test(bool test) = 0;
+		m_submit->m_commands.write(COMMAND_CREATE_DYNAMIC_VERTEX_BUFFER);
+		m_submit->m_commands.write(id);
+		m_submit->m_commands.write(count);
+		m_submit->m_commands.write(format);
 
-	/// Sets whether writing to depth buffer is enabled.
-	virtual void			set_depth_write(bool write) = 0;
+		return id;
+	}
 
-	/// Sets the depth function to use when testing depth values.
-	virtual void			set_depth_func(CompareFunction func) = 0;
+	/// Updates the data associated with the given vertex buffer @a id.
+	/// @a vertices is the array containig @a count vertex data elements of the format
+	/// specified at the creation of the buffer.
+	/// @note
+	/// @a count and @a offset together do not have to exceed the number of elements specified
+	/// at the creation of the buffer.
+	inline void update_vertex_buffer(VertexBufferId id, size_t offset, size_t count, const void* vertices)
+	{
+		m_submit->m_commands.write(COMMAND_UPDATE_VERTEX_BUFFER);
+		m_submit->m_commands.write(id);
+		m_submit->m_commands.write(offset);
+		m_submit->m_commands.write(count);
+		m_submit->m_commands.write(vertices);			
+	}
+
+	/// Destroys the given vertex buffer @a id.
+	inline void destroy_vertex_buffer(VertexBufferId id)
+	{
+		m_submit->m_commands.write(COMMAND_DESTROY_VERTEX_BUFFER);
+		m_submit->m_commands.write(id);
+	}
 
-	/// Sets whether blending is enabled.
-	virtual void			set_blending(bool blending) = 0;
+	/// Creates a new index buffer optimized for rendering static index buffers.
+	/// @a indices is the array containing @a count index data elements.
+	inline IndexBufferId create_index_buffer(size_t count, const void* indices)
+	{
+		const IndexBufferId id = m_index_buffers.create();
+
+		m_submit->m_commands.write(COMMAND_CREATE_INDEX_BUFFER);
+		m_submit->m_commands.write(id);
+		m_submit->m_commands.write(count);
+		m_submit->m_commands.write(indices);
+
+		return id;
+	}
+
+	inline IndexBufferId create_dynamic_index_buffer(size_t count)
+	{
+		const IndexBufferId id = m_index_buffers.create();
+
+		m_submit->m_commands.write(COMMAND_CREATE_DYNAMIC_INDEX_BUFFER);
+		m_submit->m_commands.write(id);
+		m_submit->m_commands.write(count);
+
+		return id;
+	}
+
+	inline void update_index_buffer(IndexBufferId id, size_t offset, size_t count, const void* indices)
+	{
+		m_submit->m_commands.write(COMMAND_UPDATE_INDEX_BUFFER);
+		m_submit->m_commands.write(id);
+		m_submit->m_commands.write(offset);
+		m_submit->m_commands.write(count);
+		m_submit->m_commands.write(indices);
+	}
 
-	///	Specifies blending parameters.
-	/// @note
-	///	This method specifies the blend equation, the blend function
-	///	for source and destination pixel values and a const blend color.
-	virtual void			set_blending_params(BlendEquation equation, BlendFunction src, BlendFunction dst, const Color4& color) = 0;
-
-	/// Sets whether writing to color buffer is enabled.
-	virtual void			set_color_write(bool write) = 0;
-				
-	virtual void 			set_front_face(FrontFace face) = 0;
-				
-	virtual void 			set_viewport_params(int32_t x, int32_t y, int32_t width, int32_t height) = 0;
-	virtual void 			get_viewport_params(int32_t& x, int32_t& y, int32_t& width, int32_t& height) = 0;
-				
-	virtual void 			set_scissor(bool scissor) = 0;
-	virtual void 			set_scissor_params(int32_t x, int32_t y, int32_t width, int32_t height) = 0;
-	virtual void 			get_scissor_params(int32_t& x, int32_t& y, int32_t& width, int32_t& height) = 0;
-				
-	virtual Mat4 			get_matrix(MatrixType type) const = 0;
-	virtual void 			set_matrix(MatrixType type, const Mat4& matrix) = 0;
-				
-	virtual void 			bind_vertex_buffer(VertexBufferId vb) const = 0;
-	//virtual void bind_render_buffer(RenderBufferId id) const = 0;
-				
-	virtual void 			draw_triangles(IndexBufferId id) const = 0;
-				
-	virtual void 			draw_lines(const float* vertices, const float* colors, uint32_t count) = 0;
+	/// Destroys the @a id index buffer.
+	inline void destroy_index_buffer(IndexBufferId id)
+	{
+		m_submit->m_commands.write(COMMAND_DESTROY_INDEX_BUFFER);
+		m_submit->m_commands.write(id);
+	}
+
+	inline TextureId create_texture(uint32_t width, uint32_t height, PixelFormat format, const void* data)
+	{
+		const TextureId id = m_textures.create();
+
+		m_submit->m_commands.write(COMMAND_CREATE_TEXTURE);
+		m_submit->m_commands.write(id);
+		m_submit->m_commands.write(width);
+		m_submit->m_commands.write(height);
+		m_submit->m_commands.write(format);
+		m_submit->m_commands.write(data);
+
+		return id;
+	}
+
+	inline void update_texture(TextureId id, uint32_t x, uint32_t y, uint32_t width, uint32_t height, const void* data)
+	{
+		m_submit->m_commands.write(COMMAND_UPDATE_TEXTURE);
+		m_submit->m_commands.write(id);
+		m_submit->m_commands.write(x);
+		m_submit->m_commands.write(y);
+		m_submit->m_commands.write(width);
+		m_submit->m_commands.write(height);
+		m_submit->m_commands.write(data);
+	}
+
+	inline void destroy_texture(TextureId id)
+	{
+		m_submit->m_commands.write(COMMAND_DESTROY_TEXTURE);
+		m_submit->m_commands.write(id);
+	}
+
+	inline ShaderId create_shader(ShaderType type, const char* text)
+	{
+		const ShaderId id = m_shaders.create();
+
+		m_submit->m_commands.write(COMMAND_CREATE_SHADER);
+		m_submit->m_commands.write(id);
+		m_submit->m_commands.write(type);
+		m_submit->m_commands.write(text);
+
+		return id;
+	}
+
+	inline void destroy_shader(ShaderId id)
+	{
+		m_submit->m_commands.write(COMMAND_DESTROY_SHADER);
+		m_submit->m_commands.write(id);
+	}
+
+	inline GPUProgramId create_gpu_program(ShaderId vertex, ShaderId pixel)
+	{
+		const GPUProgramId id = m_gpu_programs.create();
+
+		m_submit->m_commands.write(COMMAND_CREATE_GPU_PROGRAM);
+		m_submit->m_commands.write(id);
+		m_submit->m_commands.write(vertex);
+		m_submit->m_commands.write(pixel);
+
+		return id;
+	}
+
+	inline void destroy_gpu_program(GPUProgramId id)
+	{
+		m_submit->m_commands.write(COMMAND_DESTROY_GPU_PROGRAM);
+		m_submit->m_commands.write(id);
+	}
+
+	inline UniformId create_uniform(const char* name, UniformType type, uint8_t num)
+	{
+		CE_ASSERT(name_to_stock_uniform(name) == UNIFORM_COUNT, "Uniform name '%s' is a stock uniform.", name);
+
+		const UniformId id = m_uniforms.create();
+		size_t len = string::strlen(name);
+
+		CE_ASSERT(len < CROWN_MAX_UNIFORM_NAME_LENGTH, "Max uniform name length is %d", CROWN_MAX_UNIFORM_NAME_LENGTH);
+
+		m_submit->m_commands.write(COMMAND_CREATE_UNIFORM);
+		m_submit->m_commands.write(id);
+		m_submit->m_commands.write(len);
+		m_submit->m_commands.write(name, len);
+		m_submit->m_commands.write(type);
+		m_submit->m_commands.write(num);
+
+		return id;
+	}
+
+	inline void destroy_uniform(UniformId id)
+	{
+		m_submit->m_commands.write(COMMAND_DESTROY_UNIFORM);
+		m_submit->m_commands.write(id);
+	}
+
+	// 
+	// RenderTargetId create_render_target(uint16_t width, uint16_t height, RenderTargetFormat format)
+	// {
+
+	// }
+	// void destroy_render_target(RenderTargetId id)
+	// {
+
+	// }
+
+	//-----------------------------------------------------------------------------
+	inline void execute_commands(CommandBuffer& cmds)
+	{
+		bool end = false;
+
+		do
+		{
+			CommandType command;
+			cmds.read(command);
+
+			switch (command)
+			{
+				case COMMAND_INIT_RENDERER:
+				{
+					init_impl();
+					m_is_initialized = true;
+					break;
+				}
+				case COMMAND_SHUTDOWN_RENDERER:
+				{
+					shutdown_impl();
+					m_is_initialized = false;
+					break;
+				}
+				case COMMAND_CREATE_VERTEX_BUFFER:
+				{
+					VertexBufferId id;
+					size_t count;
+					VertexFormat format;
+					void* vertices;
+
+					cmds.read(id);
+					cmds.read(count);
+					cmds.read(format);
+					cmds.read(vertices);
+
+					create_vertex_buffer_impl(id, count, format, vertices);
+					break;
+				}
+				case COMMAND_CREATE_DYNAMIC_VERTEX_BUFFER:
+				{
+					VertexBufferId id;
+					size_t count;
+					VertexFormat format;
+
+					cmds.read(id);
+					cmds.read(count);
+					cmds.read(format);
+
+					create_dynamic_vertex_buffer_impl(id, count, format);
+					break;
+				}
+				case COMMAND_UPDATE_VERTEX_BUFFER:
+				{
+					VertexBufferId id;
+					size_t offset;
+					size_t count;
+					void* vertices;
+
+					cmds.read(id);
+					cmds.read(offset);
+					cmds.read(count);
+					cmds.read(vertices);
+
+					update_vertex_buffer_impl(id, offset, count, vertices);			
+					break;
+				}
+				case COMMAND_DESTROY_VERTEX_BUFFER:
+				{
+					VertexBufferId id;
+					cmds.read(id);
+
+					destroy_vertex_buffer_impl(id);
+					break;
+				}
+				case COMMAND_CREATE_INDEX_BUFFER:
+				{
+					IndexBufferId id;
+					size_t count;
+					void* indices;
+
+					cmds.read(id);
+					cmds.read(count);
+					cmds.read(indices);
+
+					create_index_buffer_impl(id, count, indices);
+					break;
+				}
+				case COMMAND_CREATE_DYNAMIC_INDEX_BUFFER:
+				{
+					IndexBufferId id;
+					size_t count;
+
+					cmds.read(id);
+					cmds.read(count);
+
+					create_dynamic_index_buffer_impl(id, count);
+					break;
+				}
+				case COMMAND_UPDATE_INDEX_BUFFER:
+				{
+					IndexBufferId id;
+					size_t offset;
+					size_t count;
+					void* indices;
+
+					cmds.read(id);
+					cmds.read(offset);
+					cmds.read(count);
+					cmds.read(indices);
+
+					update_index_buffer_impl(id, offset, count, indices);
+					break;
+				}
+				case COMMAND_DESTROY_INDEX_BUFFER:
+				{
+					IndexBufferId id;
+					cmds.read(id);
+
+					destroy_index_buffer_impl(id);
+					break;
+				}
+				case COMMAND_CREATE_TEXTURE:
+				{
+					TextureId id;
+					uint32_t width;
+					uint32_t height;
+					PixelFormat format;
+					void* data;
+
+					cmds.read(id);
+					cmds.read(width);
+					cmds.read(height);
+					cmds.read(format);
+					cmds.read(data);
+
+					create_texture_impl(id, width, height, format, data);
+					break;
+				}
+				case COMMAND_UPDATE_TEXTURE:
+				{
+					TextureId id;
+					uint32_t x;
+					uint32_t y;
+					uint32_t width;
+					uint32_t height;
+					void* data;
+
+					cmds.read(id);
+					cmds.read(x);
+					cmds.read(y);
+					cmds.read(width);
+					cmds.read(height);
+					cmds.read(data);
+
+					update_texture_impl(id, x, y, width, height, data);
+					break;
+				}
+				case COMMAND_DESTROY_TEXTURE:
+				{
+					TextureId id;
+					cmds.read(id);
+
+					destroy_texture_impl(id);
+					break;
+				}
+				case COMMAND_CREATE_SHADER:
+				{
+					ShaderId id;
+					ShaderType type;
+					char* text;
+
+					cmds.read(id);
+					cmds.read(type);
+					cmds.read(text);
+
+					create_shader_impl(id, type, text);
+					break;
+				}
+				case COMMAND_DESTROY_SHADER:
+				{
+					ShaderId id;
+					cmds.read(id);
+
+					destroy_shader_impl(id);
+					break;
+				}
+				case COMMAND_CREATE_GPU_PROGRAM:
+				{
+					GPUProgramId id;
+					ShaderId vertex;
+					ShaderId pixel;
+
+					cmds.read(id);
+					cmds.read(vertex);
+					cmds.read(pixel);
+
+					create_gpu_program_impl(id, vertex, pixel);
+					break;
+				}
+				case COMMAND_DESTROY_GPU_PROGRAM:
+				{
+					GPUProgramId id;
+					cmds.read(id);
+
+					destroy_gpu_program_impl(id);
+					break;
+				}
+				case COMMAND_CREATE_UNIFORM:
+				{
+					UniformId id;
+					size_t len;
+					char name[CROWN_MAX_UNIFORM_NAME_LENGTH];
+					UniformType type;
+					uint8_t num;
+
+					cmds.read(id);
+					cmds.read(len);
+					cmds.read(name, len);
+					name[len] = '\0';
+					cmds.read(type);
+					cmds.read(num);
+
+					create_uniform_impl(id, name, type, num);
+
+					break;
+				}
+				case COMMAND_DESTROY_UNIFORM:
+				{
+					UniformId id;
+					cmds.read(id);
+
+					destroy_uniform_impl(id);
+
+					break;
+				}
+				case COMMAND_END:
+				{
+					end = true;
+					break;
+				}
+				default:
+				{
+					CE_ASSERT(false, "Oops, unknown command");
+					break;
+				}
+			}
+		}
+		while (!end);
+
+		cmds.clear();
+	}
+
+	inline void update_uniforms(ConstantBuffer& cbuf)
+	{
+		UniformType type;
+
+		while ((type = (UniformType)cbuf.read()) != UNIFORM_END)
+		{
+			UniformId id;
+			size_t size;
+
+			cbuf.read(&id, sizeof(UniformId));
+			cbuf.read(&size, sizeof(size_t));
+			const void* data = cbuf.read(size);
+
+			update_uniform_impl(id, size, data);
+		}
+
+		cbuf.clear();
+	}
+
+	inline void set_state(uint64_t flags)
+	{
+		m_submit->set_state(flags);
+	}
+
+	inline void set_pose(const Mat4& pose)
+	{
+		m_submit->set_pose(pose);
+	}
+
+	inline void set_program(GPUProgramId program)
+	{
+		m_submit->set_program(program);
+	}
+
+	inline void set_vertex_buffer(VertexBufferId vb)
+	{
+		m_submit->set_vertex_buffer(vb);
+	}
+
+	inline void set_index_buffer(IndexBufferId ib)
+	{
+		m_submit->set_index_buffer(ib);
+	}
+
+	inline void set_uniform(UniformId id, UniformType type, void* value, uint8_t num)
+	{
+		m_submit->set_uniform(id, type, value, num);
+	}
+
+	inline void set_texture(uint8_t unit, UniformId sampler_uniform, TextureId texture, uint32_t flags)
+	{
+		m_submit->set_texture(unit, sampler_uniform, texture, flags);
+	}
+
+	inline void set_layer_render_target(uint8_t layer, RenderTargetId target)
+	{
+		m_submit->set_layer_render_target(layer, target);
+	}
+
+	inline void set_layer_clear(uint8_t layer, uint8_t flags, const Color4& color, float depth)
+	{
+		m_submit->set_layer_clear(layer, flags, color, depth);
+	}
+
+	inline void set_layer_view(uint8_t layer, const Mat4& view)
+	{
+		m_submit->set_layer_view(layer, view);
+	}
+
+	inline void set_layer_projection(uint8_t layer, const Mat4& projection)
+	{
+		m_submit->set_layer_projection(layer, projection);
+	}
+
+	inline void set_layer_viewport(uint8_t layer, uint16_t x, uint16_t y, uint16_t width, uint16_t height)
+	{
+		m_submit->set_layer_viewport(layer, x, y, width, height);
+	}
+
+	inline void set_layer_scissor(uint8_t layer, uint16_t x, uint16_t y, uint16_t width, uint16_t height)
+	{
+		m_submit->set_layer_scissor(layer, x, y, width, height);
+	}
+
+	inline void commit(uint8_t layer)
+	{
+		m_submit->commit(layer);
+	}
+
+	static int32_t render_thread(void* thiz)
+	{
+		Renderer* renderer = (Renderer*)thiz;
+		while (renderer->m_should_run)
+		{
+			renderer->render_all();
+		}
+
+		return 0;
+	}
+
+	inline void swap_contexts()
+	{
+		// Ensure COMMAND_END at the end of submit command buffer
+		m_submit->push();
+
+		RenderContext* temp = m_submit;
+		m_submit = m_draw;
+		m_draw = temp;
+
+		m_main_wait.post();
+	}
+
+	inline void frame()
+	{
+		// Signal main thread finished updating
+		m_render_wait.post();
+		m_main_wait.wait();
+	}
+
+	// Do all the processing needed to render a frame
+	inline void render_all()
+	{
+		// Waits for main thread to finish update
+		m_render_wait.wait();
+
+		swap_contexts();
+
+		execute_commands(m_draw->m_commands);
+		update_uniforms(m_draw->m_constants);
+
+		if (m_is_initialized)
+		{
+			render_impl();
+		}
+	}
+
+protected:
+
+	Allocator& m_allocator;
+	RendererImplementation* m_impl;
+
+	Thread m_thread;
+	Semaphore m_render_wait;
+	Semaphore m_main_wait;
+
+	RenderContext m_contexts[2];
+	RenderContext* m_submit;
+	RenderContext* m_draw;
+
+	// Id tables
+	IdTable<CROWN_MAX_VERTEX_BUFFERS> m_vertex_buffers;
+	IdTable<CROWN_MAX_INDEX_BUFFERS> m_index_buffers;
+	IdTable<CROWN_MAX_TEXTURES> m_textures;
+	IdTable<CROWN_MAX_SHADERS> m_shaders;
+	IdTable<CROWN_MAX_GPU_PROGRAMS> m_gpu_programs;
+	IdTable<CROWN_MAX_UNIFORMS> m_uniforms;
+	// IdTable<CROWN_MAX_RENDER_TARGETS> m_render_targets;
+
+	bool m_is_initialized;
+	bool m_should_run;
 };
 
 } // namespace crown

+ 161 - 0
engine/renderers/RendererTypes.h

@@ -0,0 +1,161 @@
+/*
+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 "IdTable.h"
+
+namespace crown
+{
+
+typedef Id VertexBufferId;
+typedef Id IndexBufferId;
+typedef Id RenderTargetId;
+typedef Id TextureId;
+typedef Id ShaderId;
+typedef Id GPUProgramId;
+typedef Id UniformId;
+
+enum ShaderType
+{
+	SHADER_VERTEX,
+	SHADER_FRAGMENT
+};
+
+enum UniformType
+{
+	UNIFORM_INTEGER_1,
+	UNIFORM_INTEGER_2,
+	UNIFORM_INTEGER_3,
+	UNIFORM_INTEGER_4,
+	UNIFORM_FLOAT_1,
+	UNIFORM_FLOAT_2,
+	UNIFORM_FLOAT_3,
+	UNIFORM_FLOAT_4,
+	UNIFORM_FLOAT_3_X_3,
+	UNIFORM_FLOAT_4_X_4,
+	UNIFORM_END
+};
+
+enum RenderTargetFormat
+{
+	RTF_RGB_8,		///< RGB values, 8-bit each
+	RTF_RGBA_8,		///< RGBA values, 8-bit each
+	RTF_D24			///< Depth
+};
+
+enum ShaderUniform
+{
+	UNIFORM_VIEW					= 0,
+	UNIFORM_MODEL					= 1,
+	UNIFORM_MODEL_VIEW				= 2,
+	UNIFORM_MODEL_VIEW_PROJECTION	= 3,
+	UNIFORM_TIME_SINCE_START		= 4,
+	UNIFORM_COUNT
+};
+
+enum ShaderAttrib
+{
+	ATTRIB_POSITION			= 0,
+	ATTRIB_NORMAL			= 1,
+	ATTRIB_COLOR			= 2,
+	ATTRIB_TEX_COORD0		= 3,
+	ATTRIB_TEX_COORD1		= 4,
+	ATTRIB_TEX_COORD2		= 5,
+	ATTRIB_TEX_COORD3		= 6,
+	ATTRIB_COUNT
+};
+
+enum VertexFormat
+{
+	VERTEX_P2 = 0,
+	VERTEX_P2_N3,
+	VERTEX_P2_C4,
+	VERTEX_P2_T2,
+	VERTEX_P2_N3_C4,
+	VERTEX_P2_N3_C4_T2,
+
+	VERTEX_P3,
+	VERTEX_P3_N3,
+	VERTEX_P3_C4,
+	VERTEX_P3_T2,
+	VERTEX_P3_N3_C4,
+	VERTEX_P3_N3_T2,
+	VERTEX_P3_N3_C4_T2,
+
+	VERTEX_COUNT
+};
+
+// [0 - 2]		-> 8-bit
+// [3 - 11] 	-> 16-bit
+// [12 - 13]	-> 24-bit
+// [14 - 23]	-> 32-bit
+// [24 - 25]	-> 48-bit
+// [26 - 31]	-> 64-bit
+// [32 - 35]	-> 96-bit
+// [36 - 39]	-> 128-bit
+// 40			-> Unknown (0-bit)
+/// Enumerates pixel formats.
+enum PixelFormat
+{
+	PIXEL_RGB_8 = 0,
+	PIXEL_RGBA_8,
+
+	PIXEL_COUNT
+};
+
+enum CommandType
+{
+	COMMAND_INIT_RENDERER,
+	COMMAND_SHUTDOWN_RENDERER,
+
+	COMMAND_CREATE_VERTEX_BUFFER,
+	COMMAND_CREATE_DYNAMIC_VERTEX_BUFFER,
+	COMMAND_UPDATE_VERTEX_BUFFER,
+	COMMAND_DESTROY_VERTEX_BUFFER,
+
+	COMMAND_CREATE_INDEX_BUFFER,
+	COMMAND_CREATE_DYNAMIC_INDEX_BUFFER,
+	COMMAND_UPDATE_INDEX_BUFFER,
+	COMMAND_DESTROY_INDEX_BUFFER,
+
+	COMMAND_CREATE_TEXTURE,
+	COMMAND_UPDATE_TEXTURE,
+	COMMAND_DESTROY_TEXTURE,
+
+	COMMAND_CREATE_SHADER,
+	COMMAND_DESTROY_SHADER,
+
+	COMMAND_CREATE_GPU_PROGRAM,
+	COMMAND_DESTROY_GPU_PROGRAM,
+
+	COMMAND_CREATE_UNIFORM,
+	COMMAND_DESTROY_UNIFORM,
+
+	COMMAND_END
+};
+
+} // namespace crown

+ 79 - 10
engine/renderers/VertexFormat.h

@@ -26,21 +26,70 @@ OTHER DEALINGS IN THE SOFTWARE.
 
 #pragma once
 
+#include "RendererTypes.h"
+
 namespace crown
 {
 
-/// Enumerates vertex formats.
-enum VertexFormat
+struct VertexFormatInfo
 {
-	VF_XY_FLOAT_32					= 0,	///< XY coordinates, 32-bit floating point each
-	VF_XYZ_FLOAT_32					= 1,	///< XYZ coordinates, 32-bit floating point each
+	bool has_attrib(ShaderAttrib attrib) const
+	{
+		return sizes[attrib] != 0;
+	}
+
+	/// Returns the number of components per @a attrib
+	size_t num_components(ShaderAttrib attrib) const
+	{
+		return (size_t) sizes[attrib];
+	}
+
+	/// Returns the byte offset between consecutive vertex @a attrib
+	size_t attrib_stride(ShaderAttrib /*attrib*/) const
+	{
+		size_t stride = 0;
+		for (uint8_t i = 0; i < ATTRIB_COUNT; i++)
+		{
+			stride += sizes[i];
+		}
+
+		return stride * sizeof(float);
+	}
+
+	/// Returns the byte offset of the first @a attrib in the format
+	size_t attrib_offset(ShaderAttrib attrib) const
+	{
+		size_t offset = 0;
+		for (uint8_t i = 0; i < attrib; i++)
+		{
+			offset += sizes[i];
+		}
+
+		return offset * sizeof(float);
+	}
 
-	VF_UV_FLOAT_32					= 2,	///< UV coordinates, 32-bit floating point each
-	VF_UVT_FLOAT_32					= 3,	///< UVT coordinates, 32-bit floating point each
+public:
+
+	uint8_t sizes[ATTRIB_COUNT];
+};
 
-	VF_XYZ_NORMAL_FLOAT_32			= 4, 	///< XYZ normal coordinates, 32-bit floating point each
+// VertexFormat to VertexFormatInfo
+const VertexFormatInfo VERTEX_FORMAT_INFO[VERTEX_COUNT] =
+{
+	{ 2, 0, 0, 0, 0, 0, 0 },
+	{ 2, 3, 0, 0, 0, 0, 0 },
+	{ 2, 0, 4, 0, 0, 0, 0 },
+	{ 2, 0, 0, 2, 0, 0, 0 },
+	{ 2, 3, 4, 0, 0, 0, 0 },
+	{ 2, 3, 4, 2, 0, 0, 0 },
 
-	VF_XYZ_UV_XYZ_NORMAL_FLOAT_32	= 5		///< XYZ coordinates, UV coordinates, XYZ normal coordinates, 32-bit floating point each
+	{ 3, 0, 0, 0, 0, 0, 0 },
+	{ 3, 3, 0, 0, 0, 0, 0 },
+	{ 3, 0, 4, 0, 0, 0, 0 },
+	{ 3, 0, 0, 2, 0, 0, 0 },
+	{ 3, 3, 4, 0, 0, 0, 0 },
+	{ 3, 3, 0, 2, 0, 0, 0 },
+	{ 3, 3, 4, 2, 0, 0, 0 }
 };
 
 class Vertex
@@ -48,10 +97,30 @@ class Vertex
 public:
 
 	/// Returns the bytes occupied by @a format
-	static size_t bytes_per_vertex(VertexFormat format);
+	static size_t bytes_per_vertex(VertexFormat format)
+	{
+		const VertexFormatInfo& info = VERTEX_FORMAT_INFO[format];
+		
+		size_t size = 0;
+		for (uint8_t i = 0; i < ATTRIB_COUNT; i++)
+		{
+			size += info.sizes[i];
+		}
+
+		// Components are always float
+		return size * sizeof(float);
+	}
 
 	/// Returns the bits occupied by @a format
-	static size_t bits_per_vertex(VertexFormat format);
+	static size_t bits_per_vertex(VertexFormat format)
+	{
+		return bytes_per_vertex(format) * 8;
+	}
+
+	static const VertexFormatInfo& info(VertexFormat format)
+	{
+		return VERTEX_FORMAT_INFO[format];
+	}
 
 private:
 

+ 0 - 33
engine/renderers/VertexShader.h

@@ -1,33 +0,0 @@
-/*
-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
-
-namespace crown
-{
-
-const uint32_t MAX_VERTEX_SHADERS = 128;
-
-} // namespace crown

+ 415 - 840
engine/renderers/gl/GLRenderer.cpp

@@ -24,1008 +24,583 @@ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 OTHER DEALINGS IN THE SOFTWARE.
 */
 
-#include <GL/glew.h>
-#include <algorithm>
-
 #include "Config.h"
 
+#if defined(LINUX) || defined(WINDOWS)
+	#include <GL/glew.h>
+#elif defined(ANDROID)
+	#include <GLES2/gl2.h>
+#else
+	#error "Oops, wrong platform"
+#endif
+
+#include <algorithm>
 #include "Allocator.h"
 #include "Assert.h"
 #include "Types.h"
 #include "GLRenderer.h"
-#include "GLUtils.h"
 #include "Log.h"
-#include "Material.h"
-#include "Vec2.h"
-#include "Vec3.h"
 #include "Vec4.h"
 #include "Mat3.h"
 #include "Mat4.h"
 #include "Device.h"
+#include "Hash.h"
+#include "StringUtils.h"
 
 namespace crown
 {
 
 //-----------------------------------------------------------------------------
-static const char* gl_error_to_string(GLenum error)
-{
-	switch (error)
-	{
-		case GL_INVALID_ENUM: return "GL_INVALID_ENUM";
-		case GL_INVALID_VALUE: return "GL_INVALID_VALUE";
-		case GL_INVALID_OPERATION: return "GL_INVALID_OPERATION";
-		case GL_OUT_OF_MEMORY: return "GL_OUT_OF_MEMORY";
-		default: return "UNKNOWN_GL_ERROR";
-	}
-}
-
-//-----------------------------------------------------------------------------
-#if defined(CROWN_DEBUG) || defined(CROWN_DEVELOPMENT)
-	#define GL_CHECK(function)\
-		function;\
-		do { GLenum error; CE_ASSERT((error = glGetError()) == GL_NO_ERROR,\
-				"OpenGL error: %s", gl_error_to_string(error)); } while (0)
-#else
-	#define GL_CHECK(function)\
-		function;
-#endif
-
-//-----------------------------------------------------------------------------
-GLRenderer::GLRenderer() :
-	m_max_texture_size(0),
-	m_max_texture_units(0),
-	m_max_vertex_indices(0),
-	m_max_vertex_vertices(0),
-	m_max_anisotropy(0.0f),
-
-	m_ambient_light_color(Color4::GRAY),
-
-	m_textures_id_table(m_allocator, MAX_TEXTURES),
-	m_active_texture_unit(0),
-
-	m_vertex_buffers_id_table(m_allocator, MAX_VERTEX_BUFFERS),
-	m_index_buffers_id_table(m_allocator, MAX_INDEX_BUFFERS),
-	m_vertex_shaders_id_table(m_allocator, MAX_VERTEX_SHADERS),
-	m_pixel_shaders_id_table(m_allocator, MAX_PIXEL_SHADERS),
-	m_gpu_programs_id_table(m_allocator, 128)
-	//m_render_buffers_id_table(m_allocator, MAX_RENDER_BUFFERS)
-{
-	m_min_max_point_size[0] = 0.0f;
-	m_min_max_point_size[1] = 0.0f;
-	m_min_max_line_width[0] = 0.0f;
-	m_min_max_line_width[1] = 0.0f;
-
-	// Initialize viewport and scissor
-	m_viewport[0] = 0;
-	m_viewport[1] = 0;
-	m_viewport[2] = 0;
-	m_viewport[3] = 0;
-
-	m_scissor[0] = 0;
-	m_scissor[1] = 0;
-	m_scissor[2] = 0;
-	m_scissor[3] = 0;
-
-	// Initialize texture units
-	for (uint32_t i = 0; i < MAX_TEXTURE_UNITS; i++)
-	{
-		m_texture_unit[i] = 0;
-		m_texture_unit_target[i] = GL_TEXTURE_2D;
-	}
-
-	// Initialize the matrices
-	for (uint32_t i = 0; i < MT_COUNT; i++)
-	{
-		m_matrix[i].load_identity();
-	}
-
-	m_model_view_matrix.load_identity();
-	m_model_view_projection_matrix.load_identity();
-}
-
-//-----------------------------------------------------------------------------
-GLRenderer::~GLRenderer()
-{
-}
-
-//-----------------------------------------------------------------------------
-void GLRenderer::init()
-{
-	m_context.create_context();
-
-	GLenum err = glewInit();
-	CE_ASSERT(err == GLEW_OK, "Failed to initialize GLEW");
-
-	GL_CHECK(glGetIntegerv(GL_MAX_TEXTURE_SIZE, &m_max_texture_size));
-	GL_CHECK(glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &m_max_texture_units));
-	GL_CHECK(glGetIntegerv(GL_MAX_ELEMENTS_INDICES, &m_max_vertex_indices));
-	GL_CHECK(glGetIntegerv(GL_MAX_ELEMENTS_VERTICES, &m_max_vertex_vertices));
-
-	// Check for anisotropic filter support
-	if (GLEW_EXT_texture_filter_anisotropic)
-	{
-		GL_CHECK(glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &m_max_anisotropy));
-	}
-
-	GL_CHECK(glGetFloatv(GL_ALIASED_POINT_SIZE_RANGE, &m_min_max_point_size[0]));
-	GL_CHECK(glGetFloatv(GL_LINE_WIDTH_RANGE, &m_min_max_line_width[0]));
-
-	Log::i("OpenGL Vendor\t: %s", glGetString(GL_VENDOR));
-	Log::i("OpenGL Renderer\t: %s", glGetString(GL_RENDERER));
-	Log::i("OpenGL Version\t: %s", glGetString(GL_VERSION));
-
-	Log::d("Min Point Size\t: %f", m_min_max_point_size[0]);
-	Log::d("Max Point Size\t: %f", m_min_max_point_size[1]);
-	Log::d("Min Line Width\t: %f", m_min_max_line_width[0]);
-	Log::d("Max Line Width\t: %f", m_min_max_line_width[1]);
-	Log::d("Max Texture Size\t: %dx%d", m_max_texture_size, m_max_texture_size);
-	Log::d("Max Texture Units\t: %d", m_max_texture_units);
-	Log::d("Max Vertex Indices\t: %d", m_max_vertex_indices);
-	Log::d("Max Vertex Vertices\t: %d", m_max_vertex_vertices);
-	Log::d("Max Anisotropy\t: %f", m_max_anisotropy);
-
-	GL_CHECK(glDisable(GL_TEXTURE_2D));
-
-	GL_CHECK(glDisable(GL_BLEND));
-	GL_CHECK(glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA));
-	GL_CHECK(glBlendEquation(GL_FUNC_ADD));
-
-	GL_CHECK(glFrontFace(GL_CCW));
-	GL_CHECK(glEnable(GL_CULL_FACE));
-	GL_CHECK(glShadeModel(GL_SMOOTH));
-
-	// Set the default framebuffer clear color
-	GL_CHECK(glClearColor(0.5f, 0.5f, 0.5f, 0.5f));
-
-	// Enable depth test
-	GL_CHECK(glEnable(GL_DEPTH_TEST));
-	GL_CHECK(glDepthFunc(GL_LEQUAL));
-	GL_CHECK(glClearDepth(1.0));
-
-	// Enable scissor test
-	GL_CHECK(glEnable(GL_SCISSOR_TEST));
-
-	// Disable dithering
-	GL_CHECK(glDisable(GL_DITHER));
-
-	// Point sprites enabled by default
-	GL_CHECK(glEnable(GL_POINT_SPRITE));
-	GL_CHECK(glTexEnvi(GL_POINT_SPRITE, GL_COORD_REPLACE, GL_TRUE));
-
-	Log::i("OpenGL Renderer initialized.");
-
-	load_default_shaders();
-}
-
-//-----------------------------------------------------------------------------
-void GLRenderer::shutdown()
-{
-	unload_default_shaders();
-
-	m_context.destroy_context();
-}
-
-//-----------------------------------------------------------------------------
-VertexBufferId GLRenderer::create_vertex_buffer(size_t count, VertexFormat format, const void* vertices)
-{
-	const VertexBufferId id = m_vertex_buffers_id_table.create();
-
-	VertexBuffer& buffer = m_vertex_buffers[id.index];
-
-	GL_CHECK(glGenBuffers(1, &buffer.gl_object));
-
-	GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER, buffer.gl_object));
-	GL_CHECK(glBufferData(GL_ARRAY_BUFFER, count * Vertex::bytes_per_vertex(format), vertices, GL_STATIC_DRAW));
-
-	buffer.count = count;
-	buffer.format = format;
-
-	return id;
-}
-
-//-----------------------------------------------------------------------------
-VertexBufferId GLRenderer::create_dynamic_vertex_buffer(size_t count, VertexFormat format, const void* vertices)
+const GLenum PRIMITIVE_TYPE_TABLE[] =
 {
-	const VertexBufferId id = m_vertex_buffers_id_table.create();
-
-	VertexBuffer& buffer = m_vertex_buffers[id.index];
-
-	GL_CHECK(glGenBuffers(1, &buffer.gl_object));
-
-	GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER, buffer.gl_object));
-	GL_CHECK(glBufferData(GL_ARRAY_BUFFER, count * Vertex::bytes_per_vertex(format), vertices, GL_STREAM_DRAW));
-
-	buffer.count = count;
-	buffer.format = format;
-
-	return id;
-}
+	GL_TRIANGLES,
+	GL_POINTS,
+	GL_LINES
+};
 
 //-----------------------------------------------------------------------------
-void GLRenderer::update_vertex_buffer(VertexBufferId id, size_t offset, size_t count, const void* vertices)
+const GLenum TEXTURE_MIN_FILTER_TABLE[] =
 {
-	CE_ASSERT(m_vertex_buffers_id_table.has(id), "Vertex buffer does not exist");
-
-	VertexBuffer& buffer = m_vertex_buffers[id.index];
-
-	GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER, buffer.gl_object));
-	GL_CHECK(glBufferSubData(GL_ARRAY_BUFFER, offset * Vertex::bytes_per_vertex(buffer.format),
-					count * Vertex::bytes_per_vertex(buffer.format), vertices));
-}
+	0, // Unused
+	GL_NEAREST,
+	GL_LINEAR,
+	GL_NEAREST_MIPMAP_LINEAR,
+	GL_LINEAR_MIPMAP_LINEAR
+};
 
 //-----------------------------------------------------------------------------
-void GLRenderer::destroy_vertex_buffer(VertexBufferId id)
+const GLenum TEXTURE_MAG_FILTER_TABLE[] =
 {
-	CE_ASSERT(m_vertex_buffers_id_table.has(id), "Vertex buffer does not exist");
-
-	VertexBuffer& buffer = m_vertex_buffers[id.index];
-
-	GL_CHECK(glDeleteBuffers(1, &buffer.gl_object));
-
-	m_vertex_buffers_id_table.destroy(id);
-}
+	0, // Unused
+	GL_NEAREST,
+	GL_LINEAR,
+	GL_LINEAR,
+	GL_LINEAR
+};
 
 //-----------------------------------------------------------------------------
-IndexBufferId GLRenderer::create_index_buffer(size_t count, const void* indices)
+const GLenum TEXTURE_WRAP_TABLE[] =
 {
-	const IndexBufferId id = m_index_buffers_id_table.create();
-
-	IndexBuffer& buffer = m_index_buffers[id.index];
-
-	GL_CHECK(glGenBuffers(1, &buffer.gl_object));
-
-	GL_CHECK(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer.gl_object));
-	GL_CHECK(glBufferData(GL_ELEMENT_ARRAY_BUFFER, count * sizeof(GLushort), indices, GL_STATIC_DRAW));
-
-	buffer.index_count = count;
-
-	return id;
-}
+	0, // Unused
+	GL_CLAMP_TO_EDGE,
+	GL_REPEAT
+};
 
 //-----------------------------------------------------------------------------
-void GLRenderer::destroy_index_buffer(IndexBufferId id)
+const GLTextureFormatInfo TEXTURE_FORMAT_TABLE[PIXEL_COUNT] =
 {
-	CE_ASSERT(m_index_buffers_id_table.has(id), "Index buffer does not exist");
-
-	IndexBuffer& buffer = m_index_buffers[id.index];
-
-	GL_CHECK(glDeleteBuffers(1, &buffer.gl_object));
-
-	m_index_buffers_id_table.destroy(id);
-}
+	{ GL_RGB, GL_RGB },
+	{ GL_RGBA, GL_RGBA}
+};
 
-//-----------------------------------------------------------------------------
-TextureId GLRenderer::create_texture(uint32_t width, uint32_t height, PixelFormat format, const void* data)
+// Keep in sync with ShaderAttrib
+const char* const SHADER_ATTRIB_NAMES[ATTRIB_COUNT] =
 {
-	const TextureId id = m_textures_id_table.create();
-
-	Texture& gl_texture = m_textures[id.index];
-
-	GL_CHECK(glGenTextures(1, &gl_texture.gl_object));
-
-	GL_CHECK(glBindTexture(GL_TEXTURE_2D, gl_texture.gl_object));
-
-	GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE));
+	"a_position",
+	"a_normal",
+	"a_color",
+	"a_tex_coord0",
+	"a_tex_coord1",
+	"a_tex_coord2",
+	"a_tex_coord3"
+};
 
-	// FIXME
-	GL_CHECK(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0,
-				 GL::pixel_format(format), GL_UNSIGNED_BYTE, data));
-
-	gl_texture.format = format;
-
-	return id;
-}
-
-//-----------------------------------------------------------------------------
-void GLRenderer::update_texture(TextureId id, uint32_t x, uint32_t y, uint32_t width, uint32_t height, const void* data)
+const char* const SHADER_UNIFORM_NAMES[] =
 {
-	CE_ASSERT(m_textures_id_table.has(id), "Texture does not exist");
+	"u_view",
+	"u_model",
+	"u_model_view",
+	"u_model_view_projection",
+	"u_time_since_start"
+};
 
-	Texture& gl_texture = m_textures[id.index];
-
-	GL_CHECK(glBindTexture(GL_TEXTURE_2D, gl_texture.gl_object));
-
-	GL_CHECK(glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, width, height, GL::pixel_format(gl_texture.format),
-					GL_UNSIGNED_BYTE, data));
-}
-
-//-----------------------------------------------------------------------------
-void GLRenderer::destroy_texture(TextureId id)
+const size_t UNIFORM_SIZE_TABLE[UNIFORM_END] =
 {
-	CE_ASSERT(m_textures_id_table.has(id), "Texture does not exist");
-
-	Texture& gl_texture = m_textures[id.index];
+	sizeof(int32_t) * 1,
+	sizeof(int32_t) * 2,
+	sizeof(int32_t) * 3,
+	sizeof(int32_t) * 4,
+	sizeof(float) * 1,
+	sizeof(float) * 2,
+	sizeof(float) * 3,
+	sizeof(float) * 4,
+	sizeof(float) * 9,
+	sizeof(float) * 16
+};
 
-	GL_CHECK(glDeleteTextures(1, &gl_texture.gl_object));
-}
-
-//-----------------------------------------------------------------------------
-VertexShaderId GLRenderer::create_vertex_shader(const char* program)
+ShaderUniform name_to_stock_uniform(const char* uniform)
 {
-	CE_ASSERT(program != NULL, "Program must be != NULL");
-
-	const VertexShaderId& id = m_vertex_shaders_id_table.create();
-
-	VertexShader& gl_shader = m_vertex_shaders[id.index];
-
-	gl_shader.gl_object = GL_CHECK(glCreateShader(GL_VERTEX_SHADER));
-
-	GL_CHECK(glShaderSource(gl_shader.gl_object, 1, &program, NULL));
-
-	GL_CHECK(glCompileShader(gl_shader.gl_object));
-
-	GLint success;
-	GL_CHECK(glGetShaderiv(gl_shader.gl_object, GL_COMPILE_STATUS, &success));
-
-	if (!success)
+	for (uint8_t i = 0; i < UNIFORM_COUNT; i++)
 	{
-		GLchar info_log[256];
-
-		GL_CHECK(glGetShaderInfoLog(gl_shader.gl_object, 256, NULL, info_log));
-
-		Log::e("Vertex shader compilation failed.");
-		Log::e("Log: %s", info_log);
-		CE_ASSERT(0, "");
+		if (string::strcmp(uniform, SHADER_UNIFORM_NAMES[i]) == 0)
+		{
+			return (ShaderUniform) i;
+		}
 	}
 
-	return id;
-}
-
-//-----------------------------------------------------------------------------
-void GLRenderer::destroy_vertex_shader(VertexShaderId id)
-{
-	CE_ASSERT(m_vertex_shaders_id_table.has(id), "Vertex shader does not exist");
-
-	VertexShader& gl_shader = m_vertex_shaders[id.index];
-
-	GL_CHECK(glDeleteShader(gl_shader.gl_object));
+	return UNIFORM_COUNT;
 }
 
-//-----------------------------------------------------------------------------
-PixelShaderId GLRenderer::create_pixel_shader(const char* program)
+/// OpenGL renderer
+class RendererImplementation
 {
-	CE_ASSERT(program != NULL, "Program must be != NULL");
-
-	const PixelShaderId& id = m_pixel_shaders_id_table.create();
-
-	PixelShader& gl_shader = m_pixel_shaders[id.index];
-
-	gl_shader.gl_object = GL_CHECK(glCreateShader(GL_FRAGMENT_SHADER));
-
-	GL_CHECK(glShaderSource(gl_shader.gl_object, 1, &program, NULL));
-
-	GL_CHECK(glCompileShader(gl_shader.gl_object));
-
-	GLint success;
-	GL_CHECK(glGetShaderiv(gl_shader.gl_object, GL_COMPILE_STATUS, &success));
+public:
 
-	if (!success)
+	//-----------------------------------------------------------------------------
+	RendererImplementation()
+		: m_max_texture_size(0), m_max_texture_units(0), m_max_vertex_indices(0), m_max_vertex_vertices(0),
+			m_max_anisotropy(0.0f), m_num_uniforms(0)
 	{
-		GLchar info_log[256];
-
-		GL_CHECK(glGetShaderInfoLog(gl_shader.gl_object, 256, NULL, info_log));
-
-		Log::e("Pixel shader compilation failed.");
-		Log::e("Log: %s", info_log);
-		CE_ASSERT(0, "");
+		m_min_max_point_size[0] = 0.0f;
+		m_min_max_point_size[1] = 0.0f;
+		m_min_max_line_width[0] = 0.0f;
+		m_min_max_line_width[1] = 0.0f;
 	}
 
-	return id;	
-}
-
-//-----------------------------------------------------------------------------
-void GLRenderer::destroy_pixel_shader(PixelShaderId id)
-{
-	CE_ASSERT(m_pixel_shaders_id_table.has(id), "Pixel shader does not exist");
-
-	PixelShader& gl_shader = m_pixel_shaders[id.index];
-
-	GL_CHECK(glDeleteShader(gl_shader.gl_object));	
-}
-
-//-----------------------------------------------------------------------------
-GPUProgramId GLRenderer::create_gpu_program(VertexShaderId vs, PixelShaderId ps)
-{
-	CE_ASSERT(m_vertex_shaders_id_table.has(vs), "Vertex shader does not exist");
-	CE_ASSERT(m_pixel_shaders_id_table.has(ps), "Pixel shader does not exist");
-
-	const GPUProgramId id = m_gpu_programs_id_table.create();
-
-	GPUProgram& gl_program = m_gpu_programs[id.index];
-
-	gl_program.gl_object = GL_CHECK(glCreateProgram());
-
-	GL_CHECK(glAttachShader(gl_program.gl_object, m_vertex_shaders[id.index].gl_object));
-	GL_CHECK(glAttachShader(gl_program.gl_object, m_pixel_shaders[id.index].gl_object));
-
-	GL_CHECK(glBindAttribLocation(gl_program.gl_object, SA_VERTEX, "vertex"));
-	GL_CHECK(glBindAttribLocation(gl_program.gl_object, SA_COORDS, "coords"));
-	GL_CHECK(glBindAttribLocation(gl_program.gl_object, SA_NORMAL, "normal"));
-
-	GL_CHECK(glLinkProgram(gl_program.gl_object));
-
-	GLint success;
-	GL_CHECK(glGetProgramiv(gl_program.gl_object, GL_LINK_STATUS, &success));
-
-	if (!success)
+	//-----------------------------------------------------------------------------
+	~RendererImplementation()
 	{
-		GLchar info_log[256];
-		GL_CHECK(glGetProgramInfoLog(gl_program.gl_object, 256, NULL, info_log));
-		Log::e("GPU program compilation failed.\n");
-		Log::e("Log: %s", info_log);
 	}
 
-	return id;
-}
-
-//-----------------------------------------------------------------------------
-void GLRenderer::destroy_gpu_program(GPUProgramId id)
-{
-	CE_ASSERT(m_gpu_programs_id_table.has(id), "GPU program does not exist");
-
-	GPUProgram& gl_program = m_gpu_programs[id.index];
-
-	GL_CHECK(glDeleteProgram(gl_program.gl_object));
-}
-
-//-----------------------------------------------------------------------------
-void GLRenderer::set_gpu_program_bool_uniform(GPUProgramId id, const char* name, bool value)
-{
-	CE_ASSERT(m_gpu_programs_id_table.has(id), "GPU program does not exist");
-
-	const GLint uniform = find_gpu_program_uniform(m_gpu_programs[id.index].gl_object, name);
-
-	GL_CHECK(glUniform1i(uniform, (GLint) value));
-}
-
-//-----------------------------------------------------------------------------
-void GLRenderer::set_gpu_program_int_uniform(GPUProgramId id, const char* name, int value)
-{
-	CE_ASSERT(m_gpu_programs_id_table.has(id), "GPU program does not exist");
-
-	const GLint uniform = find_gpu_program_uniform(m_gpu_programs[id.index].gl_object, name);
-
-	GL_CHECK(glUniform1i(uniform, (GLint) value));
-}
-
-//-----------------------------------------------------------------------------
-void GLRenderer::set_gpu_program_vec2_uniform(GPUProgramId id, const char* name, const Vec2& value)
-{
-	CE_ASSERT(m_gpu_programs_id_table.has(id), "GPU program does not exist");
-
-	const GLint uniform = find_gpu_program_uniform(m_gpu_programs[id.index].gl_object, name);
-
-	GL_CHECK(glUniform2fv(uniform, 1, value.to_float_ptr()));
-}
-
-//-----------------------------------------------------------------------------
-void GLRenderer::set_gpu_program_vec3_uniform(GPUProgramId id, const char* name, const Vec3& value)
-{
-	CE_ASSERT(m_gpu_programs_id_table.has(id), "GPU program does not exist");
-
-	const GLint uniform = find_gpu_program_uniform(m_gpu_programs[id.index].gl_object, name);
-
-	GL_CHECK(glUniform3fv(uniform, 1, value.to_float_ptr()));
-}
-
-//-----------------------------------------------------------------------------
-void GLRenderer::set_gpu_program_vec4_uniform(GPUProgramId id, const char* name, const Vec4& value)
-{
-	CE_ASSERT(m_gpu_programs_id_table.has(id), "GPU program does not exist");
-
-	const GLint uniform = find_gpu_program_uniform(m_gpu_programs[id.index].gl_object, name);
-
-	GL_CHECK(glUniform4fv(uniform, 1, value.to_float_ptr()));
-}
-
-//-----------------------------------------------------------------------------
-void GLRenderer::set_gpu_porgram_mat3_uniform(GPUProgramId id, const char* name, const Mat3& value)
-{
-	CE_ASSERT(m_gpu_programs_id_table.has(id), "GPU program does not exist");
-
-	const GLint uniform = find_gpu_program_uniform(m_gpu_programs[id.index].gl_object, name);
-
-	GL_CHECK(glUniformMatrix3fv(uniform, 1, GL_FALSE, value.to_float_ptr()));
-}
-
-//-----------------------------------------------------------------------------
-void GLRenderer::set_gpu_program_mat4_uniform(GPUProgramId id, const char* name, const Mat4& value)
-{
-	CE_ASSERT(m_gpu_programs_id_table.has(id), "GPU program does not exist");
-
-	const GLint uniform = find_gpu_program_uniform(m_gpu_programs[id.index].gl_object, name);
-
-	GL_CHECK(glUniformMatrix4fv(uniform, 1, GL_FALSE, value.to_float_ptr()));
-}
-
-//-----------------------------------------------------------------------------
-void GLRenderer::set_gpu_program_sampler_uniform(GPUProgramId id, const char* name, uint32_t value)
-{
-	CE_ASSERT(m_gpu_programs_id_table.has(id), "GPU program does not exist");
-
-	const GLint uniform = find_gpu_program_uniform(m_gpu_programs[id.index].gl_object, name);
-
-	GL_CHECK(glUniform1i(uniform, (GLint) value));	
-}
-
-//-----------------------------------------------------------------------------
-void GLRenderer::bind_gpu_program(GPUProgramId id) const
-{
-	CE_ASSERT(m_gpu_programs_id_table.has(id), "GPU program does not exist");
-
-	const GPUProgram& gl_program = m_gpu_programs[id.index];
-
-	GL_CHECK(glUseProgram(gl_program.gl_object));
-}
-
-//-----------------------------------------------------------------------------
-// RenderBufferId GLRenderer::create_render_buffer(uint32_t width, uint32_t height, PixelFormat format)
-// {
-// 	const RenderBufferId id = m_render_buffers_id_table.create();
-
-// 	GLRenderBuffer& buffer = m_render_buffers[id.index];
-
-// 	if (GLEW_EXT_framebuffer_object)
-// 	{
-// 		GL_CHECK(glGenFramebuffersEXT(1, &buffer.GL_CHECK(gl_frame_buffer));
-// 		GL_CHECK(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, buffer.GL_CHECK(gl_frame_buffer));
-
-// 		GL_CHECK(glGenRenderbuffersEXT(1, &buffer.GL_CHECK(gl_render_buffer));
-// 		GL_CHECK(glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, buffer.GL_CHECK(gl_render_buffer));
-
-// 		GL_CHECK(glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGBA8, width, height));
-
-// 		GL_CHECK(glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, buffer.GL_CHECK(gl_render_buffer));
-
-// 		GL_CHECK(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0));
-// 	}
-
-// 	return id;
-// }
-
-//-----------------------------------------------------------------------------
-// void GLRenderer::destroy_render_buffer(RenderBufferId id)
-// {
-// 	GLRenderBuffer& buffer = m_render_buffers[id.index];
-
-// 	if (GLEW_EXT_framebuffer_object)
-// 	{
-// 		GL_CHECK(glDeleteFramebuffersEXT(1, &buffer.GL_CHECK(gl_frame_buffer));
-// 		GL_CHECK(glDeleteRenderbuffersEXT(1, &buffer.GL_CHECK(gl_render_buffer));
-// 	}
-
-// 	m_render_buffers_id_table.destroy(id);
-// }
+	//-----------------------------------------------------------------------------
+	void init()
+	{
+		m_gl_context.create_context();
+
+		#if defined(LINUX) || defined(WINDOW)
+			GLenum err = glewInit();
+			CE_ASSERT(err == GLEW_OK, "Failed to initialize GLEW");
+		#endif
+
+		GL_CHECK(glGetIntegerv(GL_MAX_TEXTURE_SIZE, &m_max_texture_size));
+		GL_CHECK(glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &m_max_texture_units));
+		// GL_CHECK(glGetIntegerv(GL_MAX_ELEMENTS_INDICES, &m_max_vertex_indices));
+		// GL_CHECK(glGetIntegerv(GL_MAX_ELEMENTS_VERTICES, &m_max_vertex_vertices));
+
+		GL_CHECK(glGetFloatv(GL_ALIASED_POINT_SIZE_RANGE, &m_min_max_point_size[0]));
+		// GL_CHECK(glGetFloatv(GL_LINE_WIDTH_RANGE, &m_min_max_line_width[0]));
+
+		Log::i("OpenGL Vendor        : %s", glGetString(GL_VENDOR));
+		Log::i("OpenGL Renderer      : %s", glGetString(GL_RENDERER));
+		Log::i("OpenGL Version       : %s", glGetString(GL_VERSION));
+		Log::i("GLSL Version         : %s", glGetString(GL_SHADING_LANGUAGE_VERSION));
+
+		Log::d("Min Point Size       : %f", m_min_max_point_size[0]);
+		Log::d("Max Point Size       : %f", m_min_max_point_size[1]);
+		Log::d("Min Line Width       : %f", m_min_max_line_width[0]);
+		Log::d("Max Line Width       : %f", m_min_max_line_width[1]);
+		Log::d("Max Texture Size     : %dx%d", m_max_texture_size, m_max_texture_size);
+		Log::d("Max Texture Units    : %d", m_max_texture_units);
+		Log::d("Max Vertex Indices   : %d", m_max_vertex_indices);
+		Log::d("Max Vertex Vertices  : %d", m_max_vertex_vertices);
 
-//-----------------------------------------------------------------------------
-void GLRenderer::set_clear_color(const Color4& color)
-{
-	GL_CHECK(glClearColor(color.r, color.g, color.b, color.a));
-}
+		GL_CHECK(glDisable(GL_BLEND));
+		GL_CHECK(glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA));
+		GL_CHECK(glBlendEquation(GL_FUNC_ADD));
 
-//-----------------------------------------------------------------------------
-void GLRenderer::set_ambient_light(const Color4& color)
-{
-	m_ambient_light_color = color;
-}
+		#if defined(LINUX) || defined(WINDOWS)
+			// Point sprites enabled by default
+			GL_CHECK(glEnable(GL_POINT_SPRITE));
+			GL_CHECK(glTexEnvi(GL_POINT_SPRITE, GL_COORD_REPLACE, GL_TRUE));
+		#endif
 
-//-----------------------------------------------------------------------------
-void GLRenderer::bind_texture(uint32_t unit, TextureId texture)
-{
-	CE_ASSERT(m_textures_id_table.has(texture), "Texture does not exist");
+		Log::i("OpenGL Renderer initialized.");
+	}
 
-	if (!activate_texture_unit(unit))
+	//-----------------------------------------------------------------------------
+	void shutdown()
 	{
-		return;
+		m_gl_context.destroy_context();
 	}
 
-	m_texture_unit_target[unit] = GL_TEXTURE_2D;
-	m_texture_unit[unit] = m_textures[texture.index].gl_object;
-
-	GL_CHECK(glEnable(m_texture_unit_target[unit]));
-	GL_CHECK(glBindTexture(m_texture_unit_target[unit], m_texture_unit[unit]));
-}
+	//-----------------------------------------------------------------------------
+	void render(RenderContext& context)
+	{
+		//RenderTargetId old_rt;
+		//old_rt.id = INVALID_ID;
+		uint8_t layer = 0xFF;
 
-//-----------------------------------------------------------------------------
-void GLRenderer::set_texturing(uint32_t unit, bool texturing)
-{
-	if (!activate_texture_unit(unit))
-		return;
+		for (uint32_t s = 0; s < context.m_num_states; s++)
+		{
+			const uint64_t key_s = context.m_keys[s];
+			RenderKey key;
+			key.decode(key_s);
+			const RenderState& cur_state = context.m_states[s];
+			const uint64_t flags = cur_state.m_flags;
+			//const RenderTargetId& cur_rt = context.m_targets[layer];
+
+			// Check if layer changed
+			if (key.m_layer != layer)
+			{
+				layer = key.m_layer;
+
+				// Viewport
+				const ViewRect& viewport = context.m_viewports[layer];
+				GL_CHECK(glViewport(viewport.m_x, viewport.m_y, viewport.m_width, viewport.m_height));
+
+				// Clear frame/depth buffer
+				const ClearState& clear = context.m_clears[layer];
+				if (clear.m_flags & (CLEAR_COLOR | CLEAR_DEPTH))
+				{
+					GLbitfield gl_clear = (clear.m_flags & CLEAR_COLOR) ? GL_COLOR_BUFFER_BIT : 0;
+					gl_clear |= (clear.m_flags & CLEAR_DEPTH) ? GL_DEPTH_BUFFER_BIT : 0;
+					GL_CHECK(glClearColor(clear.m_color.r, clear.m_color.g, clear.m_color.b, clear.m_color.a));
+					#if defined(LINUX) || defined(WINDOWS)
+						GL_CHECK(glClearDepth(clear.m_depth));
+					#elif defined(ANDROID)
+						GL_CHECK(glClearDepthf(clear.m_depth));
+					#endif
+					GL_CHECK(glClear(gl_clear));
+				}
+
+				GL_CHECK(glEnable(GL_DEPTH_TEST));
+			}
+
+			// Scissor
+			const ViewRect& scissor = context.m_scissors[layer];
+			if (scissor.area() != 0)
+			{
+				GL_CHECK(glEnable(GL_SCISSOR_TEST));
+				GL_CHECK(glScissor(scissor.m_x, scissor.m_y, scissor.m_width, scissor.m_height));
+			}
+			else
+			{
+				GL_CHECK(glDisable(GL_SCISSOR_TEST));
+			}
+
+			// Depth write
+			if (flags & (STATE_DEPTH_WRITE))
+			{
+				GL_CHECK(glDepthMask(flags & STATE_DEPTH_WRITE));
+			}
+
+			// Color/Alpha write
+			if (flags & (STATE_COLOR_WRITE | STATE_ALPHA_WRITE))
+			{
+				GLboolean cw = !!(flags & STATE_COLOR_WRITE);
+				GLboolean aw = !!(flags & STATE_ALPHA_WRITE);
+				GL_CHECK(glColorMask(cw, cw, cw, aw));
+			}
+
+			// Face culling
+			if (flags & STATE_CULL_CW)
+			{
+				GL_CHECK(glEnable(GL_CULL_FACE));
+				GL_CHECK(glCullFace(GL_BACK));
+			}
+			else if (flags & STATE_CULL_CCW)
+			{
+				GL_CHECK(glEnable(GL_CULL_FACE));
+				GL_CHECK(glCullFace(GL_FRONT));
+			}
+			else
+			{
+				GL_CHECK(glDisable(GL_CULL_FACE));
+			}
+
+			// Bind GPU program
+			if (cur_state.program.id != INVALID_ID)
+			{
+				const GPUProgram& gpu_program = m_gpu_programs[cur_state.program.index];
+				GL_CHECK(glUseProgram(gpu_program.m_id));
+				// Not necessarily here...
+				gpu_program.commit();
+
+				for (uint8_t uniform = 0; uniform < gpu_program.m_num_stock_uniforms; uniform++)
+				{
+					const GLint& uniform_location = gpu_program.m_stock_uniform_locations[uniform];
+					const Mat4& view = context.m_view_matrices[layer];
+					const Mat4& projection = context.m_projection_matrices[layer];
+
+					switch (gpu_program.m_stock_uniforms[uniform])
+					{
+						case UNIFORM_VIEW:
+						{
+							GL_CHECK(glUniformMatrix4fv(uniform_location, 1, GL_FALSE, view.to_float_ptr()));
+							break;
+						}
+						case UNIFORM_MODEL:
+						{
+							GL_CHECK(glUniformMatrix4fv(uniform_location, 1, GL_FALSE, cur_state.pose.to_float_ptr()));
+							break;
+						}
+						case UNIFORM_MODEL_VIEW:
+						{
+							GL_CHECK(glUniformMatrix4fv(uniform_location, 1, GL_FALSE, (view *
+															cur_state.pose).to_float_ptr()));
+							break;
+						}
+						case UNIFORM_MODEL_VIEW_PROJECTION:
+						{
+							GL_CHECK(glUniformMatrix4fv(uniform_location, 1, GL_FALSE, (projection * view *
+															cur_state.pose).to_float_ptr()));
+							break;
+						}
+						case UNIFORM_TIME_SINCE_START:
+						{
+							GL_CHECK(glUniform1f(uniform_location, device()->time_since_start()));
+							break;
+						}
+						default:
+						{
+							CE_ASSERT(false, "Oops, wrong stock uniform!");
+							break;
+						}
+					}
+				}
+			}
+			else
+			{
+				GL_CHECK(glUseProgram(0));
+			}
+
+			// Bind array buffers
+			const VertexBufferId& vb = cur_state.vb;
+			if (vb.id != INVALID_ID)
+			{
+				const VertexBuffer& vertex_buffer = m_vertex_buffers[vb.index];
+				glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer.m_id);
+
+				const GPUProgram& gpu_program = m_gpu_programs[cur_state.program.index];
+				gpu_program.bind_attributes(vertex_buffer.m_format);
+			}
+			else
+			{
+				GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER, 0));
+			}
+
+			const IndexBufferId& ib = cur_state.ib;
+			if (ib.id != INVALID_ID)
+			{
+				const IndexBuffer& index_buffer = m_index_buffers[ib.index];
+				uint32_t prim_type = (flags & STATE_PRIMITIVE_MASK) >> STATE_PRIMITIVE_SHIFT;
+				GLenum gl_prim_type = PRIMITIVE_TYPE_TABLE[prim_type];
+				GL_CHECK(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer.m_id));
+				GL_CHECK(glDrawElements(gl_prim_type, index_buffer.m_index_count, GL_UNSIGNED_SHORT, 0));
+			}
+			else
+			{
+				GL_CHECK(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
+			}
+
+			// Bind textures
+			{
+				uint64_t flags = STATE_TEXTURE_0;
+				for (uint32_t unit = 0; unit < STATE_MAX_TEXTURES; unit++)
+				{
+					const Sampler& sampler = cur_state.samplers[unit];
+
+					if (sampler.sampler_id.id != INVALID_ID)
+					{
+						switch (sampler.flags & SAMPLER_MASK)
+						{
+							case SAMPLER_TEXTURE:
+							{
+								Texture& texture = m_textures[sampler.sampler_id.index];
+								texture.commit(unit, sampler.flags);
+								break;
+							}
+							default:
+							{
+								CE_ASSERT(false, "Oops, sampler unknown");
+								break;
+							}
+						}
+					}
+
+					flags <<= 1;
+				}
+			}
+		}
 
-	if (texturing)
-	{
-		GL_CHECK(glEnable(m_texture_unit_target[unit]));
-	}
-	else
-	{
-		GL_CHECK(glDisable(m_texture_unit_target[unit]));
+		GL_CHECK(glFinish());
+		m_gl_context.swap_buffers();
 	}
-}
 
-//-----------------------------------------------------------------------------
-void GLRenderer::set_texture_wrap(uint32_t unit, TextureWrap wrap)
-{
-	GLenum gl_wrap = GL::texture_wrap(wrap);
+private:
 
-	GL_CHECK(glTexParameteri(m_texture_unit_target[unit], GL_TEXTURE_WRAP_S, gl_wrap));
-	GL_CHECK(glTexParameteri(m_texture_unit_target[unit], GL_TEXTURE_WRAP_T, gl_wrap));
-}
+	GLContext			m_gl_context;
 
-//-----------------------------------------------------------------------------
-void GLRenderer::set_texture_filter(uint32_t unit, TextureFilter filter)
-{
-	if (!activate_texture_unit(unit))
-		return;
+	// Limits
+	int32_t				m_max_texture_size;
+	int32_t				m_max_texture_units;
+	int32_t				m_max_vertex_indices;
+	int32_t				m_max_vertex_vertices;
 
-	GLint min_filter;
-	GLint mag_filter;
+	float				m_max_anisotropy;
+	float				m_min_max_point_size[2];
+	float				m_min_max_line_width[2];
 
-	GL::texture_filter(filter, min_filter, mag_filter);
+	VertexBuffer		m_vertex_buffers[CROWN_MAX_VERTEX_BUFFERS];
+	IndexBuffer			m_index_buffers[CROWN_MAX_INDEX_BUFFERS];
+	Texture				m_textures[CROWN_MAX_TEXTURES];
+	Shader				m_shaders[CROWN_MAX_SHADERS];
+	GPUProgram			m_gpu_programs[CROWN_MAX_GPU_PROGRAMS];
+	uint32_t			m_num_uniforms;
+	Uniform				m_uniforms[CROWN_MAX_UNIFORMS];
+	RenderTarget		m_render_targets[CROWN_MAX_RENDER_TARGETS];
 
-	GL_CHECK(glTexParameteri(m_texture_unit_target[unit], GL_TEXTURE_MIN_FILTER, min_filter));
-	GL_CHECK(glTexParameteri(m_texture_unit_target[unit], GL_TEXTURE_MAG_FILTER, mag_filter));
-}
+private:
 
-//-----------------------------------------------------------------------------
-void GLRenderer::set_backface_culling(bool culling)
-{
-	if (culling)
-	{
-		GL_CHECK(glEnable(GL_CULL_FACE));
-	}
-	else
-	{
-		GL_CHECK(glDisable(GL_CULL_FACE));
-	}
-}
+	friend class		Renderer;
+};
 
 //-----------------------------------------------------------------------------
-void GLRenderer::set_depth_test(bool test)
+Renderer::Renderer(Allocator& a)
+	: m_allocator(a), m_impl(NULL), m_thread("render-thread"), m_submit(&m_contexts[0]), m_draw(&m_contexts[1]),
+		m_is_initialized(false), m_should_run(false)
 {
-	if (test)
-	{
-		GL_CHECK(glEnable(GL_DEPTH_TEST));
-	}
-	else
-	{
-		GL_CHECK(glDisable(GL_DEPTH_TEST));
-	}
+	m_impl = CE_NEW(a, RendererImplementation);
 }
 
 //-----------------------------------------------------------------------------
-void GLRenderer::set_depth_write(bool write)
+Renderer::~Renderer()
 {
-	GL_CHECK(glDepthMask((GLboolean) write));
+	CE_DELETE(m_allocator, m_impl);
 }
 
 //-----------------------------------------------------------------------------
-void GLRenderer::set_depth_func(CompareFunction func)
+void Renderer::init_impl()
 {
-	GLenum gl_func = GL::compare_function(func);
-
-	GL_CHECK(glDepthFunc(gl_func));
+	m_impl->init();
 }
 
 //-----------------------------------------------------------------------------
-void GLRenderer::set_blending(bool blending)
+void Renderer::shutdown_impl()
 {
-	if (blending)
-	{
-		GL_CHECK(glEnable(GL_BLEND));
-	}
-	else
-	{
-		GL_CHECK(glDisable(GL_BLEND));
-	}
+	m_impl->shutdown();
 }
 
 //-----------------------------------------------------------------------------
-void GLRenderer::set_blending_params(BlendEquation equation, BlendFunction src, BlendFunction dst, const Color4& color)
+void Renderer::render_impl()
 {
-	GLenum gl_equation = GL::blend_equation(equation);
+	m_impl->render(*m_draw);
 
-	GL_CHECK(glBlendEquation(gl_equation));
-
-	GLenum gl_src_factor = GL::blend_function(src);
-	GLenum gl_dst_factor = GL::blend_function(dst);
-
-	GL_CHECK(glBlendFunc(gl_src_factor, gl_dst_factor));
-
-	GL_CHECK(glBlendColor(color.r, color.g, color.b, color.a));
+	m_draw->clear();
 }
 
 //-----------------------------------------------------------------------------
-void GLRenderer::set_color_write(bool write)
+void Renderer::create_vertex_buffer_impl(VertexBufferId id, size_t count, VertexFormat format, const void* vertices)
 {
-	if (write)
-	{
-		GL_CHECK(glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE));
-	}
-	else
-	{
-		GL_CHECK(glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE));
-	}
+	m_impl->m_vertex_buffers[id.index].create(count, format, vertices);
 }
 
 //-----------------------------------------------------------------------------
-void GLRenderer::set_front_face(FrontFace face)
+void Renderer::create_dynamic_vertex_buffer_impl(VertexBufferId id, size_t count, VertexFormat format)
 {
-	const GLenum gl_face = (face == FF_CCW) ? GL_CCW : GL_CW;
-
-	GL_CHECK(glFrontFace(gl_face));
+	m_impl->m_vertex_buffers[id.index].create(count, format, NULL);
 }
 
 //-----------------------------------------------------------------------------
-void GLRenderer::set_viewport_params(int32_t x, int32_t y, int32_t width, int32_t height)
+void Renderer::update_vertex_buffer_impl(VertexBufferId id, size_t offset, size_t count, const void* vertices)
 {
-	m_viewport[0] = x;
-	m_viewport[1] = y;
-	m_viewport[2] = width;
-	m_viewport[3] = height;
-
-	GL_CHECK(glViewport(x, y, width, height));
+	m_impl->m_vertex_buffers[id.index].update(offset, count, vertices);
 }
 
 //-----------------------------------------------------------------------------
-void GLRenderer::get_viewport_params(int32_t& x, int32_t& y, int32_t& width, int32_t& height)
+void Renderer::destroy_vertex_buffer_impl(VertexBufferId id)
 {
-	x = m_viewport[0];
-	y = m_viewport[1];
-	width = m_viewport[2];
-	height = m_viewport[3];
+	m_impl->m_vertex_buffers[id.index].destroy();
 }
 
 //-----------------------------------------------------------------------------
-void GLRenderer::set_scissor(bool scissor)
+void Renderer::create_index_buffer_impl(IndexBufferId id, size_t count, const void* indices)
 {
-	if (scissor)
-	{
-		GL_CHECK(glEnable(GL_SCISSOR_TEST));
-	}
-	else
-	{
-		GL_CHECK(glDisable(GL_SCISSOR_TEST));
-	}
+	m_impl->m_index_buffers[id.index].create(count, indices);
 }
 
 //-----------------------------------------------------------------------------
-void GLRenderer::set_scissor_params(int32_t x, int32_t y, int32_t width, int32_t height)
+void Renderer::create_dynamic_index_buffer_impl(IndexBufferId id, size_t count)
 {
-	m_scissor[0] = x;
-	m_scissor[1] = y;
-	m_scissor[2] = width;
-	m_scissor[3] = height;
-
-	GL_CHECK(glScissor(x, y, width, height));
+	m_impl->m_index_buffers[id.index].create(count, NULL);
 }
 
 //-----------------------------------------------------------------------------
-void GLRenderer::get_scissor_params(int32_t& x, int32_t& y, int32_t& width, int32_t& height)
+void Renderer::update_index_buffer_impl(IndexBufferId id, size_t offset, size_t count, const void* indices)
 {
-	x = m_scissor[0];
-	y = m_scissor[1];
-	width = m_scissor[2];
-	height = m_scissor[3];
+	m_impl->m_index_buffers[id.index].update(offset, count, indices);	
 }
 
 //-----------------------------------------------------------------------------
-void GLRenderer::frame()
+void Renderer::destroy_index_buffer_impl(IndexBufferId id)
 {
-	// Clear frame/depth buffer
-	GL_CHECK(glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT));
-
-	// Bind the default gpu program
-	bind_gpu_program(m_default_gpu_program);
-
-	set_gpu_program_mat4_uniform(m_default_gpu_program, "mvp_matrix", m_model_view_projection_matrix);
-	set_gpu_program_vec3_uniform(m_default_gpu_program, "color", Vec3(0, 1, 0));
-
-	GL_CHECK(glFinish());
-
-	m_context.swap_buffers();
+	m_impl->m_index_buffers[id.index].destroy();
 }
 
 //-----------------------------------------------------------------------------
-Mat4 GLRenderer::get_matrix(MatrixType type) const
+void Renderer::create_texture_impl(TextureId id, uint32_t width, uint32_t height, PixelFormat format, const void* data)
 {
-	return m_matrix[type];
+	m_impl->m_textures[id.index].create(width, height, format, data);
 }
 
 //-----------------------------------------------------------------------------
-void GLRenderer::set_matrix(MatrixType type, const Mat4& matrix)
+void Renderer::update_texture_impl(TextureId id, uint32_t x, uint32_t y, uint32_t width, uint32_t height, const void* data)
 {
-	m_matrix[type] = matrix;
-
-	switch (type)
-	{
-		case MT_VIEW:
-		case MT_MODEL:
-		{
-			m_model_view_matrix = m_matrix[MT_VIEW] * m_matrix[MT_MODEL];
-			break;
-		}
-		case MT_PROJECTION:
-		{
-			m_model_view_projection_matrix =  m_matrix[MT_PROJECTION] * m_model_view_matrix;
-			break;
-		}
-		default:
-		{
-			break;
-			CE_ASSERT(0, "");
-		}
-	}
+	m_impl->m_textures[id.index].update(x, y, width, height, data);	
 }
 
 //-----------------------------------------------------------------------------
-void GLRenderer::bind_vertex_buffer(VertexBufferId vb) const
+void Renderer::destroy_texture_impl(TextureId id)
 {
-	CE_ASSERT(m_vertex_buffers_id_table.has(vb), "Vertex buffer does not exist");
-
-	const VertexBuffer& vertex_buffer = m_vertex_buffers[vb.index];
-
-	GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer.gl_object));
-
-	switch (vertex_buffer.format)
-	{
-		case VF_XY_FLOAT_32:
-		{
-			GL_CHECK(glEnableVertexAttribArray(SA_VERTEX));
-			GL_CHECK(glVertexAttribPointer(SA_VERTEX, 2, GL_FLOAT, GL_FALSE, 0, 0));
-			break;
-		}
-		case VF_XYZ_FLOAT_32:
-		{
-			GL_CHECK(glEnableVertexAttribArray(SA_VERTEX));
-			GL_CHECK(glVertexAttribPointer(SA_VERTEX, 3, GL_FLOAT, GL_FALSE, 0, 0));
-			break;
-		}
-		case VF_UV_FLOAT_32:
-		{
-			GL_CHECK(glEnableVertexAttribArray(SA_COORDS));
-			GL_CHECK(glVertexAttribPointer(SA_COORDS, 2, GL_FLOAT, GL_FALSE, 0, 0));
-			break;
-		}
-		case VF_UVT_FLOAT_32:
-		{
-			GL_CHECK(glEnableVertexAttribArray(SA_COORDS));
-			GL_CHECK(glVertexAttribPointer(SA_COORDS, 3, GL_FLOAT, GL_FALSE, 0, 0));
-			break;
-		}
-		case VF_XYZ_NORMAL_FLOAT_32:
-		{
-			GL_CHECK(glEnableVertexAttribArray(SA_NORMAL));
-			GL_CHECK(glVertexAttribPointer(SA_NORMAL, 3, GL_FLOAT, GL_FALSE, 0, 0));
-			break;
-		}
-		case VF_XYZ_UV_XYZ_NORMAL_FLOAT_32:
-		{
-			break;
-		}
-		default:
-		{
-			CE_ASSERT(0, "Vertex format unknown");
-			break;
-		}
-	}
+	m_impl->m_textures[id.index].destroy();
 }
 
 //-----------------------------------------------------------------------------
-void GLRenderer::draw_triangles(IndexBufferId id) const
+void Renderer::create_shader_impl(ShaderId id, ShaderType type, const char* text)
 {
-	CE_ASSERT(m_index_buffers_id_table.has(id), "Index buffer does not exist");
-
-	const IndexBuffer& index_buffer = m_index_buffers[id.index];
-
-	GL_CHECK(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer.gl_object));
-
-	GL_CHECK(glDrawElements(GL_TRIANGLES, index_buffer.index_count, GL_UNSIGNED_SHORT, 0));
+	m_impl->m_shaders[id.index].create(type, text);
 }
 
 //-----------------------------------------------------------------------------
-// void GLRenderer::bind_render_buffer(RenderBufferId id) const
-// {
-// 	CE_ASSERT(m_render_buffers_id_table.has(id), "Render buffer does not exist");
-
-// 	const GLRenderBuffer& render_buffer = m_render_buffers[id.index];
-// }
-
-//-----------------------------------------------------------------------------
-void GLRenderer::draw_lines(const float* vertices, const float* colors, uint32_t count)
+void Renderer::destroy_shader_impl(ShaderId id)
 {
-	GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER, 0));
-	GL_CHECK(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
-
-	GL_CHECK(glEnableClientState(GL_VERTEX_ARRAY));
-	GL_CHECK(glEnableClientState(GL_COLOR_ARRAY));
-
-	GL_CHECK(glVertexPointer(3, GL_FLOAT, 0, vertices));
-	GL_CHECK(glColorPointer(4, GL_FLOAT, 0, colors));
-
-	GL_CHECK(glDrawArrays(GL_LINES, 0, count));
-
-	GL_CHECK(glDisableClientState(GL_COLOR_ARRAY));
-	GL_CHECK(glDisableClientState(GL_VERTEX_ARRAY));
+	m_impl->m_shaders[id.index].destroy();
 }
 
 //-----------------------------------------------------------------------------
-void GLRenderer::load_default_shaders()
+void Renderer::create_gpu_program_impl(GPUProgramId id, ShaderId vertex, ShaderId pixel)
 {
-	static const char* vs_text =
-		"in vec4 vertex;"
-		"in vec2 coords;"
-		"uniform mat4 mvp_matrix;"
-		"uniform vec3 color;"
-
-		"void main(void)"
-		"{"
-		"	gl_Position = mvp_matrix * vertex;"
-
-		"	gl_FrontColor = vec4(color, 1.0);"
-		"}";
-
-	static const char* ps_text = 
-		"void main(void)"
-		"{"
-		"	gl_FragColor = gl_Color;"
-		"}";
-
-	m_default_vertex_shader = create_vertex_shader(vs_text);
-	m_default_pixel_shader = create_pixel_shader(ps_text);
-
-	// Create and bind the default program
-	m_default_gpu_program = create_gpu_program(m_default_vertex_shader, m_default_pixel_shader);
+	Shader& vs = m_impl->m_shaders[vertex.index];
+	Shader& ps = m_impl->m_shaders[pixel.index];
+	m_impl->m_gpu_programs[id.index].create(vs, ps, m_impl->m_num_uniforms, m_impl->m_uniforms);
 }
 
 //-----------------------------------------------------------------------------
-void GLRenderer::unload_default_shaders()
+void Renderer::destroy_gpu_program_impl(GPUProgramId id)
 {
-	destroy_pixel_shader(m_default_pixel_shader);
-	destroy_vertex_shader(m_default_vertex_shader);
-
-	destroy_gpu_program(m_default_gpu_program);
+	m_impl->m_gpu_programs[id.index].destroy();
 }
 
 //-----------------------------------------------------------------------------
-void GLRenderer::reload_default_shaders()
+void Renderer::create_uniform_impl(UniformId id, const char* name, UniformType type, uint8_t num)
 {
+	m_impl->m_uniforms[id.index].create(name, type, num);
+	m_impl->m_num_uniforms++;
 }
 
 //-----------------------------------------------------------------------------
-bool GLRenderer::activate_texture_unit(uint32_t unit)
+void Renderer::update_uniform_impl(UniformId id, size_t size, const void* data)
 {
-	if (unit >= (uint32_t) m_max_texture_units)
-	{
-		return false;
-	}
-
-	GL_CHECK(glActiveTexture(GL_TEXTURE0 + unit));
-	m_active_texture_unit = unit;
-
-	return true;
+	m_impl->m_uniforms[id.index].update(size, data);
 }
 
 //-----------------------------------------------------------------------------
-GLint GLRenderer::find_gpu_program_uniform(GLuint program, const char* name) const
+void Renderer::destroy_uniform_impl(UniformId id)
 {
-	GLint uniform = GL_CHECK(glGetUniformLocation(program, name));
+	m_impl->m_uniforms[id.index].destroy();
+	m_impl->m_num_uniforms--;
+}
 
-	CE_ASSERT(uniform != -1, "Uniform does not exist");
+// //-----------------------------------------------------------------------------
+// void Renderer::create_render_target_impl(RenderTargetId id, uint16_t width, uint16_t height, RenderTargetFormat format)
+// {
 
-	return uniform;
-}
+// }
 
-//-----------------------------------------------------------------------------
-Renderer* Renderer::create(Allocator& a)
-{
-	return CE_NEW(a, GLRenderer);
-}
+// //-----------------------------------------------------------------------------
+// void Renderer::destroy_render_target_impl(RenderTargetId id)
+// {
 
-//-----------------------------------------------------------------------------
-void Renderer::destroy(Allocator& a, Renderer* renderer)
-{
-	CE_DELETE(a, renderer);
-}
+// }
 
 } // namespace crown
-

+ 493 - 199
engine/renderers/gl/GLRenderer.h

@@ -26,252 +26,546 @@ OTHER DEALINGS IN THE SOFTWARE.
 
 #pragma once
 
-#include <GL/glew.h>
+#include "Config.h"
+
+#if defined(LINUX) || defined(WINDOWS)
+	#include <GL/glew.h>
+#elif defined(ANDROID)
+	#include <GLES2/gl2.h>
+#else
+	#error "Oops, wrong platform"
+#endif
 
 #include "Renderer.h"
-#include "Texture.h"
-#include "VertexBuffer.h"
-#include "IndexBuffer.h"
-#include "RenderBuffer.h"
-#include "VertexShader.h"
-#include "PixelShader.h"
 #include "IdTable.h"
 #include "Resource.h"
 #include "GLContext.h"
 #include "HeapAllocator.h"
+#include "VertexFormat.h"
+#include "Allocator.h"
 
 namespace crown
 {
 
-const uint32_t MAX_TEXTURE_UNITS = 8;
-
 //-----------------------------------------------------------------------------
-struct Texture
+struct GLTextureFormatInfo
 {
-	GLuint				gl_object;
-	PixelFormat			format;
+	GLenum internal_format;
+	GLenum format;
 };
 
-//-----------------------------------------------------------------------------
-struct VertexBuffer
-{
-	GLuint				gl_object;
-	size_t				count;
-	VertexFormat		format;
-};
+extern const GLenum TEXTURE_MIN_FILTER_TABLE[];
+extern const GLenum TEXTURE_MAG_FILTER_TABLE[];
+extern const GLenum TEXTURE_WRAP_TABLE[];
+extern const GLTextureFormatInfo TEXTURE_FORMAT_TABLE[PIXEL_COUNT];
+extern const char* const SHADER_ATTRIB_NAMES[ATTRIB_COUNT];
+extern const char* const SHADER_UNIFORM_NAMES[];
+extern const size_t UNIFORM_SIZE_TABLE[UNIFORM_END];
+extern ShaderUniform name_to_stock_uniform(const char* uniform);
 
 //-----------------------------------------------------------------------------
-struct IndexBuffer
+static const char* gl_error_to_string(GLenum error)
 {
-	GLuint				gl_object;
-	uint32_t			index_count;
-};
+	switch (error)
+	{
+		case GL_INVALID_ENUM: return "GL_INVALID_ENUM";
+		case GL_INVALID_VALUE: return "GL_INVALID_VALUE";
+		case GL_INVALID_OPERATION: return "GL_INVALID_OPERATION";
+		case GL_OUT_OF_MEMORY: return "GL_OUT_OF_MEMORY";
+		default: return "UNKNOWN_GL_ERROR";
+	}
+}
 
 //-----------------------------------------------------------------------------
-struct RenderBuffer
-{
-	GLuint				gl_frame_buffer;
-	GLuint				gl_render_buffer;
-};
+#if defined(CROWN_DEBUG) || defined(CROWN_DEVELOPMENT)
+	#define GL_CHECK(function)\
+		function;\
+		do { GLenum error; CE_ASSERT((error = glGetError()) == GL_NO_ERROR,\
+				"OpenGL error: %s", gl_error_to_string(error)); } while (0)
+#else
+	#define GL_CHECK(function)\
+		function;
+#endif
 
 //-----------------------------------------------------------------------------
-struct VertexShader
+struct VertexBuffer
 {
-	GLuint				gl_object;
-};
+	//-----------------------------------------------------------------------------
+	void create(size_t count, VertexFormat format, const void* vertices)
+	{
+		GL_CHECK(glGenBuffers(1, &m_id));
+		GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER, m_id));
+		GL_CHECK(glBufferData(GL_ARRAY_BUFFER, count * Vertex::bytes_per_vertex(format), vertices,
+			(vertices == NULL) ? GL_STREAM_DRAW : GL_STATIC_DRAW));
+		GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER, 0));
+
+		m_count = count;
+		m_format = format;
+	}
+
+	//-----------------------------------------------------------------------------
+	void update(size_t offset, size_t count, const void* vertices)
+	{
+		GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER, m_id));
+		GL_CHECK(glBufferSubData(GL_ARRAY_BUFFER, offset * Vertex::bytes_per_vertex(m_format),
+									count * Vertex::bytes_per_vertex(m_format), vertices));
+		GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER, 0));
+	}
+
+	//-----------------------------------------------------------------------------
+	void destroy()
+	{
+		GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER, 0));
+		GL_CHECK(glDeleteBuffers(1, &m_id));
+	}
 
-//-----------------------------------------------------------------------------
-struct PixelShader
-{
-	GLuint				gl_object;
+public:
+
+	GLuint			m_id;
+	size_t			m_count;
+	VertexFormat	m_format;
 };
 
 //-----------------------------------------------------------------------------
-struct GPUProgram
+struct IndexBuffer
 {
-	GLuint				gl_object;
-};
+	//-----------------------------------------------------------------------------
+	void create(size_t count, const void* indices)
+	{
+		GL_CHECK(glGenBuffers(1, &m_id));
+		GL_CHECK(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_id));
+		GL_CHECK(glBufferData(GL_ELEMENT_ARRAY_BUFFER, count * sizeof(GLushort), indices,
+					(indices == NULL) ? GL_STREAM_DRAW : GL_STATIC_DRAW));
+		GL_CHECK(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
+
+		m_index_count = count;
+	}
+
+	//-----------------------------------------------------------------------------
+	void update(size_t offset, size_t count, const void* indices)
+	{
+		GL_CHECK(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_id));
+		GL_CHECK(glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, offset * sizeof(uint16_t),
+									count * sizeof(uint16_t), indices));
+		GL_CHECK(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
+	}
+
+	//-----------------------------------------------------------------------------
+	void destroy()
+	{
+		GL_CHECK(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
+		GL_CHECK(glDeleteBuffers(1, &m_id));
+	}
 
-/// OpenGL renderer
-class GLRenderer : public Renderer
-{
 public:
 
-						GLRenderer();
-						~GLRenderer();
-
-	void				init();
-	void				shutdown();
-
-	// Vertex buffers
-	VertexBufferId		create_vertex_buffer(size_t count, VertexFormat format, const void* vertices);
-	VertexBufferId		create_dynamic_vertex_buffer(size_t count, VertexFormat format, const void* vertices);
-	void				update_vertex_buffer(VertexBufferId id, size_t offset, size_t count, const void* vertices);
-	void				destroy_vertex_buffer(VertexBufferId id);
-
-	// Index buffers
-	IndexBufferId		create_index_buffer(size_t count, const void* indices);
-	void				destroy_index_buffer(IndexBufferId id);
-
-	// Textures
-	TextureId			create_texture(uint32_t width, uint32_t height, PixelFormat format, const void* data);
-	void				update_texture(TextureId id, uint32_t x, uint32_t y, uint32_t width, uint32_t height, const void* data);
-	void				destroy_texture(TextureId id);
-
-	void				bind_texture(uint32_t unit, TextureId texture);
-	void				set_texturing(uint32_t unit, bool texturing);
-	void				set_texture_wrap(uint32_t unit, TextureWrap wrap);
-	void				set_texture_filter(uint32_t unit, TextureFilter filter);
-
-	// Vertex shaders
-	VertexShaderId		create_vertex_shader(const char* program);
-	void				destroy_vertex_shader(VertexShaderId id);
-
-	// Pixel shaders
-	PixelShaderId 		create_pixel_shader(const char* program);
-	void				destroy_pixel_shader(PixelShaderId id);
-
-	// GPU programs
-	GPUProgramId		create_gpu_program(VertexShaderId vs, PixelShaderId ps);
-	void				destroy_gpu_program(GPUProgramId id);
-
-	void				set_gpu_program_bool_uniform(GPUProgramId id, const char* name, bool value);
-	void				set_gpu_program_int_uniform(GPUProgramId id, const char* name, int value);
-
-	void				set_gpu_program_vec2_uniform(GPUProgramId id, const char* name, const Vec2& value);
-	void				set_gpu_program_vec3_uniform(GPUProgramId id, const char* name, const Vec3& value);
-	void				set_gpu_program_vec4_uniform(GPUProgramId id, const char* name, const Vec4& value);
-
-	void				set_gpu_porgram_mat3_uniform(GPUProgramId id, const char* name, const Mat3& value);
-	void				set_gpu_program_mat4_uniform(GPUProgramId id, const char* name, const Mat4& value);
-
-	void				set_gpu_program_sampler_uniform(GPUProgramId id, const char* name, uint32_t value);
-
-	void				bind_gpu_program(GPUProgramId id) const;
-
-	// Frame buffers
-	// RenderBufferId	create_render_buffer(uint32_t width, uint32_t height, PixelFormat format);
-	// void				destroy_render_buffer(RenderBufferId id);
-
-	void				frame();
-
-	void				set_clear_color(const Color4& color);
-
-	// Lighting
-	void				set_ambient_light(const Color4& color);
-
-	void				set_backface_culling(bool culling);
-
-	// Fragment operations
-	void				set_depth_test(bool test);
-	void				set_depth_write(bool write);
-	void				set_depth_func(CompareFunction func);
-
-	void				set_blending(bool blending);
-	void				set_blending_params(BlendEquation equation, BlendFunction src, BlendFunction dst, const Color4& color);
-	void				set_color_write(bool write);
-
-	void				set_front_face(FrontFace face);
-
-	void				set_viewport_params(int32_t x, int32_t y, int32_t width, int32_t height);
-	void				get_viewport_params(int32_t& x, int32_t& y, int32_t& width, int32_t& height);
-
-	void				set_scissor(bool scissor);
-	void				set_scissor_params(int32_t x, int32_t y, int32_t width, int32_t height);
-	void				get_scissor_params(int32_t& x, int32_t& y, int32_t& width, int32_t& height);
-
-	Mat4				get_matrix(MatrixType type) const;
-	void				set_matrix(MatrixType type, const Mat4& matrix);
-
-	void				bind_vertex_buffer(VertexBufferId vb) const;
-	//void				bind_render_buffer(RenderBufferId id) const;
-
-	void				draw_triangles(IndexBufferId id) const;
-
-	void				draw_lines(const float* vertices, const float* colors, uint32_t count);
-
-private:
-
-	// Loads the default shaders
-	void				load_default_shaders();
-	void				unload_default_shaders();
-	void				reload_default_shaders();
-
-	// Activates a texture unit and returns true if succes
-	bool				activate_texture_unit(uint32_t unit);
-	bool				activate_light(uint32_t light);
-
-	// Shaders
-	GLint				find_gpu_program_uniform(GLuint program, const char* name) const;
-
-	// GL error checking
-	void				check_gl_errors() const;
-
-private:
+	GLuint		m_id;
+	uint32_t	m_index_count;
+};
 
-	HeapAllocator		m_allocator;
+//-----------------------------------------------------------------------------
+struct Uniform
+{
+	Uniform()
+	{
+		string::strncpy(m_name, "", CROWN_MAX_UNIFORM_NAME_LENGTH);
+	}
+
+	void create(const char* name, UniformType type, uint8_t num)
+	{
+		string::strncpy(m_name, name, CROWN_MAX_UNIFORM_NAME_LENGTH);
+		m_type = type;
+		m_num = num;
+
+		size_t size = UNIFORM_SIZE_TABLE[type] * num;
+		m_data = default_allocator().allocate(size);
+		memset(m_data, 0, size);
+
+		// Log::d("Uniform created, name = %s, type = %d, num = %d, size = %d", m_name, type, num, size);
+	}
+
+	void update(size_t size, const void* data)
+	{
+		// Log::d("Uniform updated, new size = %d, new ptr = %d", size, *((int32_t*)data));
+		memcpy(m_data, data, size);
+	}
+
+	void destroy()
+	{
+		default_allocator().deallocate(m_data);
+	}
 
-	GLContext			m_context;
+public:
 
-	// Matrices
-	Mat4				m_matrix[MT_COUNT];
+	char m_name[CROWN_MAX_UNIFORM_NAME_LENGTH];
+	UniformType m_type;
+	uint8_t m_num;
+	void* m_data;
+};
 
-	Mat4				m_model_view_matrix;
-	Mat4				m_model_view_projection_matrix;
+//-----------------------------------------------------------------------------
+struct Shader
+{
+	//-----------------------------------------------------------------------------
+	void create(ShaderType type, const char* text)
+	{
+		m_id = GL_CHECK(glCreateShader(type == SHADER_VERTEX ? GL_VERTEX_SHADER : GL_FRAGMENT_SHADER));
+
+		GL_CHECK(glShaderSource(m_id, 1, &text, NULL));
+		GL_CHECK(glCompileShader(m_id));
+
+		GLint success;
+		GL_CHECK(glGetShaderiv(m_id, GL_COMPILE_STATUS, &success));
+
+		if (!success)
+		{
+			GLchar info_log[2048];
+			GL_CHECK(glGetShaderInfoLog(m_id, 2048, NULL, info_log));
+			CE_ASSERT(false, "Shader compilation failed\n\n%s", info_log);
+		}
+	}
+
+	//-----------------------------------------------------------------------------
+	void destroy()
+	{
+		GL_CHECK(glDeleteShader(m_id));
+	}
 
-	// Limits
-	int32_t				m_max_texture_size;
-	int32_t				m_max_texture_units;
-	int32_t				m_max_vertex_indices;
-	int32_t				m_max_vertex_vertices;
+public:
 
-	float				m_max_anisotropy;
-	float				m_min_max_point_size[2];
-	float				m_min_max_line_width[2];
+	GLuint m_id;
+};
 
-	// Viewport and scissor
-	int32_t				m_viewport[4];
-	int32_t				m_scissor[4];
+//-----------------------------------------------------------------------------
+struct Texture
+{
+	//-----------------------------------------------------------------------------
+	void create(uint32_t width, uint32_t height, PixelFormat format, const void* data)
+	{
+		GL_CHECK(glGenTextures(1, &m_id));
+		GL_CHECK(glBindTexture(GL_TEXTURE_2D, m_id));
+
+		#if defined(LINUX) || defined(WINDOWS)
+			GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE));
+		#endif
+
+		GLenum internal_fmt = TEXTURE_FORMAT_TABLE[format].internal_format;
+		GLenum fmt = TEXTURE_FORMAT_TABLE[format].format;
+
+		GL_CHECK(glTexImage2D(GL_TEXTURE_2D, 0, internal_fmt, width, height, 0,
+					 			fmt, GL_UNSIGNED_BYTE, data));
+		GL_CHECK(glBindTexture(GL_TEXTURE_2D, 0));
+
+		m_target = GL_TEXTURE_2D;
+		m_format = format;
+	}
+
+	//-----------------------------------------------------------------------------
+	void update(uint32_t x, uint32_t y, uint32_t width, uint32_t height, const void* data)
+	{
+		GL_CHECK(glBindTexture(GL_TEXTURE_2D, m_id));
+		GL_CHECK(glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, width, height, GL_RGBA,
+									GL_UNSIGNED_BYTE, data));
+		GL_CHECK(glBindTexture(GL_TEXTURE_2D, 0));
+	}
+
+	//-----------------------------------------------------------------------------
+	void set_sampler_state(uint32_t flags)
+	{
+		GLenum min_filter = TEXTURE_MIN_FILTER_TABLE[(flags & TEXTURE_FILTER_MASK) >> TEXTURE_FILTER_SHIFT];
+		GLenum mag_filter = TEXTURE_MAG_FILTER_TABLE[(flags & TEXTURE_FILTER_MASK) >> TEXTURE_FILTER_SHIFT];
+		GLenum wrap = TEXTURE_WRAP_TABLE[(flags & TEXTURE_WRAP_MASK) >> TEXTURE_WRAP_SHIFT];
+
+		GL_CHECK(glTexParameteri(m_target, GL_TEXTURE_WRAP_S, wrap));
+		GL_CHECK(glTexParameteri(m_target, GL_TEXTURE_WRAP_T, wrap));
+
+		GL_CHECK(glTexParameteri(m_target, GL_TEXTURE_MIN_FILTER, min_filter));
+		GL_CHECK(glTexParameteri(m_target, GL_TEXTURE_MAG_FILTER, mag_filter));
+	}
+
+	//-----------------------------------------------------------------------------
+	void destroy()
+	{
+		GL_CHECK(glBindTexture(m_target, 0));
+		GL_CHECK(glDeleteTextures(1, &m_id));
+	}
+
+	//-----------------------------------------------------------------------------
+	void commit(uint8_t unit, uint32_t flags)
+	{
+		GL_CHECK(glActiveTexture(GL_TEXTURE0 + unit));
+		GL_CHECK(glEnable(m_target));
+		GL_CHECK(glBindTexture(m_target, m_id));
+
+		set_sampler_state(flags);
+	}
 
-	// Lighting
-	Color4				m_ambient_light_color;
+public:
 
-	// Texture management
-	IdTable 			m_textures_id_table;
-	Texture				m_textures[MAX_TEXTURES];
+	GLuint			m_id;
+	GLenum			m_target;      // Always GL_TEXTURE_2D
+	uint32_t		m_width;
+	uint32_t		m_height;
+	PixelFormat		m_format;
+};
 
-	uint32_t			m_active_texture_unit;
-	GLuint				m_texture_unit[MAX_TEXTURE_UNITS];
-	GLenum				m_texture_unit_target[MAX_TEXTURE_UNITS];
+//-----------------------------------------------------------------------------
+struct GPUProgram
+{
+	//-----------------------------------------------------------------------------
+	void create(const Shader& vertex, const Shader& pixel, uint32_t num_uniforms, Uniform* uniforms)
+	{
+		m_id = GL_CHECK(glCreateProgram());
+
+		GL_CHECK(glAttachShader(m_id, vertex.m_id));
+		GL_CHECK(glAttachShader(m_id, pixel.m_id));
+
+		GL_CHECK(glLinkProgram(m_id));
+		GLint success;
+		GL_CHECK(glGetProgramiv(m_id, GL_LINK_STATUS, &success));
+		if (!success)
+		{
+			GLchar info_log[2048];
+			GL_CHECK(glGetProgramInfoLog(m_id, 2048, NULL, info_log));
+			CE_ASSERT(false, "GPU program compilation failed:\n%s", info_log);
+		}
+
+		GL_CHECK(glValidateProgram(m_id));
+		GLint valid;
+		GL_CHECK(glGetProgramiv(m_id, GL_VALIDATE_STATUS, &valid));
+		if (!valid)
+		{
+			GLchar info_log[2048];
+			GL_CHECK(glGetProgramInfoLog(m_id, 2048, NULL, info_log));
+			CE_ASSERT(false, "GPU program validation failed:\n%s", info_log);
+		}
+
+		// Find active attribs/uniforms
+		GLint num_active_attribs;
+		GLint num_active_uniforms;
+		GL_CHECK(glGetProgramiv(m_id, GL_ACTIVE_ATTRIBUTES, &num_active_attribs));
+		GL_CHECK(glGetProgramiv(m_id, GL_ACTIVE_UNIFORMS, &num_active_uniforms));
+
+		Log::d("Found %d active attribs", num_active_attribs);
+		Log::d("Found %d active uniforms", num_active_uniforms);
+
+		// Find active attribs/uniforms max length
+		GLint max_attrib_length;
+		GLint max_uniform_length;
+		GL_CHECK(glGetProgramiv(m_id, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &max_attrib_length));
+		GL_CHECK(glGetProgramiv(m_id, GL_ACTIVE_UNIFORM_MAX_LENGTH, &max_uniform_length));
+
+		for (GLint attrib = 0; attrib < num_active_attribs; attrib++)
+		{
+			GLint attrib_size;
+			GLenum attrib_type;
+			char attrib_name[1024];
+			GL_CHECK(glGetActiveAttrib(m_id, attrib, max_attrib_length, NULL, &attrib_size, &attrib_type, attrib_name));
+
+			GLint attrib_location = GL_CHECK(glGetAttribLocation(m_id, attrib_name));
+			Log::d("Attrib %d: name = '%s' location = '%d'", attrib, attrib_name, attrib_location);
+		}
+
+		m_num_active_attribs = 0;
+		for (uint32_t attrib = 0; attrib < ATTRIB_COUNT; attrib++)
+		{
+			GLint loc = GL_CHECK(glGetAttribLocation(m_id, SHADER_ATTRIB_NAMES[attrib]));
+			if (loc != -1)
+			{
+				m_active_attribs[m_num_active_attribs] = (ShaderAttrib) attrib;
+				m_num_active_attribs++;
+				m_attrib_locations[attrib] = loc;
+			}
+		}
+
+		m_num_stock_uniforms = 0;
+		m_num_uniforms = 0;
+		for (GLint uniform = 0; uniform < num_active_uniforms; uniform++)
+		{
+			GLint uniform_size;
+			GLenum uniform_type;
+			char uniform_name[1024];
+			GL_CHECK(glGetActiveUniform(m_id, uniform, max_uniform_length, NULL, &uniform_size, &uniform_type, uniform_name));
+			GLint uniform_location = GL_CHECK(glGetUniformLocation(m_id, uniform_name));
+
+			ShaderUniform stock_uniform = name_to_stock_uniform(uniform_name);
+			if (stock_uniform != UNIFORM_COUNT)
+			{
+				m_stock_uniforms[m_num_stock_uniforms] = stock_uniform;
+				m_stock_uniform_locations[m_num_stock_uniforms] = uniform_location;
+				m_num_stock_uniforms++;
+			}
+			else
+			{
+				for (uint32_t i = 0; i < num_uniforms; i++)
+				{
+					if (string::strcmp(uniforms[i].m_name, uniform_name) == 0)
+					{
+						m_uniforms[m_num_uniforms] = uniforms[i].m_type;
+						m_uniform_info[m_num_uniforms].loc = uniform_location;
+						m_uniform_info[m_num_uniforms].data = uniforms[i].m_data;
+						m_num_uniforms++;
+					}
+				}
+			}
+
+			Log::d("Uniform %d: name = '%s' location = '%d' stock = %s", uniform, uniform_name, uniform_location,
+						(stock_uniform != UNIFORM_COUNT) ? "yes" : "no");
+		}
+	}
+
+	//-----------------------------------------------------------------------------
+	void destroy()
+	{
+		GL_CHECK(glUseProgram(0));
+		GL_CHECK(glDeleteProgram(m_id));
+	}
+
+	//-----------------------------------------------------------------------------
+	void bind_attributes(VertexFormat format) const
+	{
+		// Bind all active attributes
+		for (uint8_t i = 0; i < m_num_active_attribs; i++)
+		{
+			ShaderAttrib attrib = m_active_attribs[i];
+			GLint loc = m_attrib_locations[attrib];
+
+			const VertexFormatInfo& info = Vertex::info(format);
+
+			if (loc != -1 && info.has_attrib(attrib))
+			{
+				GL_CHECK(glEnableVertexAttribArray(loc));
+				GL_CHECK(glVertexAttribPointer(loc, info.num_components(attrib), GL_FLOAT, GL_FALSE, info.attrib_stride(attrib),
+										(GLvoid*)(uintptr_t) info.attrib_offset(attrib)));
+			}
+		}
+	}
+
+	//-----------------------------------------------------------------------------
+	void commit() const
+	{
+		for (uint8_t i = 0; i < m_num_uniforms; i++)
+		{
+			const UniformType type = m_uniforms[i];
+			const GLint loc = m_uniform_info[i].loc;
+			const void* data = m_uniform_info[i].data;
+
+			switch (type)
+			{
+				case UNIFORM_INTEGER_1:   GL_CHECK(glUniform1iv(loc, 1, (const GLint*)data)); break;
+				case UNIFORM_INTEGER_2:   GL_CHECK(glUniform2iv(loc, 2, (const GLint*)data)); break;
+				case UNIFORM_INTEGER_3:   GL_CHECK(glUniform3iv(loc, 3, (const GLint*)data)); break;				
+				case UNIFORM_INTEGER_4:   GL_CHECK(glUniform4iv(loc, 4, (const GLint*)data)); break;
+				case UNIFORM_FLOAT_1:     GL_CHECK(glUniform1fv(loc, 1, (const GLfloat*)data)); break;
+				case UNIFORM_FLOAT_2:     GL_CHECK(glUniform2fv(loc, 2, (const GLfloat*)data)); break;
+				case UNIFORM_FLOAT_3:     GL_CHECK(glUniform3fv(loc, 3, (const GLfloat*)data)); break;
+				case UNIFORM_FLOAT_4:     GL_CHECK(glUniform4fv(loc, 4, (const GLfloat*)data)); break;
+				case UNIFORM_FLOAT_3_X_3: GL_CHECK(glUniformMatrix3fv(loc, 9, GL_FALSE, (const GLfloat*)data)); break;
+				case UNIFORM_FLOAT_4_X_4: GL_CHECK(glUniformMatrix4fv(loc, 16, GL_FALSE, (const GLfloat*)data)); break;
+				default: CE_ASSERT(false, "Oops, unknown uniform type"); break;
+			}
+		}
+	}
 
-	// Vertex/Index buffer management
-	IdTable				m_vertex_buffers_id_table;
-	VertexBuffer		m_vertex_buffers[MAX_VERTEX_BUFFERS];
+public:
 
-	IdTable				m_index_buffers_id_table;
-	IndexBuffer			m_index_buffers[MAX_INDEX_BUFFERS];
+	GLuint				m_id;
 
-	// Vertex shader management
-	IdTable 			m_vertex_shaders_id_table;
-	VertexShader		m_vertex_shaders[MAX_VERTEX_SHADERS];
+	uint8_t				m_num_active_attribs;
+	ShaderAttrib		m_active_attribs[ATTRIB_COUNT];
+	GLint				m_attrib_locations[ATTRIB_COUNT];
 
-	// Pixel shader management
-	IdTable 			m_pixel_shaders_id_table;
-	PixelShader			m_pixel_shaders[MAX_PIXEL_SHADERS];
+	uint8_t				m_num_stock_uniforms;
+	ShaderUniform		m_stock_uniforms[UNIFORM_COUNT];
+	GLint				m_stock_uniform_locations[UNIFORM_COUNT];
 
-	// GPU program management
-	IdTable 			m_gpu_programs_id_table;
-	GPUProgram			m_gpu_programs[128];
+	struct LocAndData
+	{
+		GLint loc;
+		void* data;
+	};
 
-	// Render buffer management
-	//IdTable			m_render_buffers_id_table;
-	//GLRenderBuffer	m_render_buffers[MAX_RENDER_BUFFERS];
+	uint8_t				m_num_uniforms;
+	UniformType			m_uniforms[16];
+	LocAndData			m_uniform_info[16];
+};
 
-	// Default shaders
-	VertexShaderId		m_default_vertex_shader;
-	PixelShaderId		m_default_pixel_shader;
-	GPUProgramId		m_default_gpu_program;
+//-----------------------------------------------------------------------------
+struct RenderTarget
+{
+	void create(uint16_t /*width*/, uint16_t /*height*/, RenderTargetFormat /*format*/)
+	{
+		// // Create and bind FBO
+		// GL_CHECK(glGenFramebuffersEXT(1, &m_gl_fbo));
+		// GL_CHECK(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_gl_fbo));
+
+		// GLuint renderedTexture;
+		// glGenTextures(1, &renderedTexture);
+		 
+		// // "Bind" the newly created texture : all future texture functions will modify this texture
+		// glBindTexture(GL_TEXTURE_2D, renderedTexture);
+		 
+		// // Give an empty image to OpenGL ( the last "0" )
+		// glTexImage2D(GL_TEXTURE_2D, 0,GL_RGB, 1024, 768, 0,GL_RGB, GL_UNSIGNED_BYTE, 0);
+		 
+		// // Poor filtering. Needed !
+		// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+		// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+
+
+		// // Create color/depth attachments
+		// switch (format)
+		// {
+		// 	case RTF_RGBA_8:
+		// 	case RTF_D24:
+		// 	{
+		// 		if (format == RTF_RGBA_8)
+		// 		{
+		// 			GL_CHECK(glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,
+  //                      GL_COLOR_ATTACHMENT0_EXT,
+  //                      GL_TEXTURE_2D,
+  //                      renderedTexture,
+  //                      0));
+		// 			break;
+		// 		}
+		// 		else if (format == RTF_D24)
+		// 		{
+		// 			GL_CHECK(glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT24, width, height));
+		// 			GL_CHECK(glFramebufferRenderbufferEXT(GL_DRAW_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, m_gl_rbo));
+		// 		}
+
+		// 		break;
+		// 	}
+		// 	default:
+		// 	{
+		// 		CE_ASSERT(false, "Oops, render target format not supported!");
+		// 		break;
+		// 	}
+		// }
+
+		// GLenum status = glCheckFramebufferStatusEXT(GL_DRAW_FRAMEBUFFER_EXT);
+		// CE_ASSERT(status == GL_FRAMEBUFFER_COMPLETE_EXT, "Oops, framebuffer incomplete!");
+
+		// GL_CHECK(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0));
+
+		// m_width = width;
+		// m_height = height;
+		// m_format = format;
+	}
+
+	void destroy()
+	{
+		// GL_CHECK(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0));
+		// GL_CHECK(glDeleteFramebuffersEXT(1, &m_gl_fbo));
+
+		// GL_CHECK(glDeleteRenderbuffersEXT(1, &m_gl_rbo));
+	}
+
+	uint16_t m_width;
+	uint16_t m_height;
+	RenderTargetFormat m_format;
+	GLuint m_gl_fbo;
+	GLuint m_gl_rbo;
 };
 
 } // namespace crown
-

+ 0 - 139
engine/renderers/gl/GLUtils.h

@@ -1,139 +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.
-*/
-
-#pragma once
-
-#include <GL/glew.h>
-#include "Texture.h"
-#include "Material.h"
-#include "PixelFormat.h"
-
-namespace crown
-{
-
-/// OpenGL utilities for converting from wrapped names to GL names and vice-versa.
-class GL
-{
-public:
-
-	static GLenum			compare_function(CompareFunction function);
-	static GLenum			blend_function(BlendFunction function);
-	static GLenum			blend_equation(BlendEquation equation);
-	static GLenum			texture_wrap(TextureWrap wrap);
-	static void				texture_filter(TextureFilter filter, GLint& minFilter, GLint& magFilter);
-	static GLenum			polygon_mode(PolygonMode mode);
-	static GLenum			pixel_format(PixelFormat format);
-	static PixelFormat		pixel_format_from_gl_format(GLenum format);
-
-private:
-
-	static const GLenum		COMPARE_FUNCTION_TABLE[CF_COUNT];
-	static const GLenum		BLEND_FUNCTION_TABLE[BF_COUNT];
-	static const GLenum		BLEND_EQUATION_TABLE[BE_COUNT];
-	static const GLenum		TEXTURE_WRAP_TABLE[TW_COUNT];
-	static const GLenum		TEXTURE_MIN_FILTER_TABLE[TF_COUNT];
-	static const GLenum		TEXTURE_MAG_FILTER_TABLE[TF_COUNT];
-	static const GLenum		POLYGON_MODE_TABLE[PM_COUNT];
-
-	// Disable construction
-	GL();
-};
-
-//-----------------------------------------------------------------------------
-inline GLenum GL::compare_function(CompareFunction function)
-{
-	return COMPARE_FUNCTION_TABLE[function];
-}
-
-//-----------------------------------------------------------------------------
-inline GLenum GL::blend_function(BlendFunction function)
-{
-	return BLEND_FUNCTION_TABLE[function];
-}
-
-//-----------------------------------------------------------------------------
-inline GLenum GL::blend_equation(BlendEquation equation)
-{
-	return BLEND_EQUATION_TABLE[equation];
-}
-
-//-----------------------------------------------------------------------------
-inline GLenum GL::texture_wrap(TextureWrap wrap)
-{
-	return TEXTURE_WRAP_TABLE[wrap];
-}
-
-//-----------------------------------------------------------------------------
-inline void GL::texture_filter(TextureFilter filter, GLint& minFilter, GLint& magFilter)
-{
-	minFilter = TEXTURE_MIN_FILTER_TABLE[filter];
-	magFilter = TEXTURE_MAG_FILTER_TABLE[filter];
-}
-
-//-----------------------------------------------------------------------------
-inline GLenum GL::polygon_mode(PolygonMode mode)
-{
-	return POLYGON_MODE_TABLE[mode];
-}
-
-//-----------------------------------------------------------------------------
-inline GLenum GL::pixel_format(PixelFormat format)
-{
-	switch (format)
-	{
-		case PF_RGBA_8:
-			return GL_RGBA;
-		case PF_RGB_8:
-			return GL_RGB;
-		case PF_LA_8:
-			return GL_LUMINANCE_ALPHA;
-		case PF_L_8:
-			return GL_LUMINANCE;
-		default:
-			return GL_RGB;
-	}
-}
-
-//-----------------------------------------------------------------------------
-inline PixelFormat GL::pixel_format_from_gl_format(GLenum format)
-{
-	switch (format)
-	{
-		case GL_RGBA:
-			return PF_RGBA_8;
-		case GL_RGB:
-			return PF_RGB_8;
-		case GL_LUMINANCE_ALPHA:
-			return PF_LA_8;
-		case GL_LUMINANCE:
-			return PF_L_8;
-		default:
-			return PF_RGB_8;
-	}
-}
-
-} // namespace crown
-

+ 142 - 0
engine/renderers/gl/egl/GLContext.cpp

@@ -0,0 +1,142 @@
+/*
+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 <GLES2/gl2.h>
+
+#include "Config.h"
+#include "Assert.h"
+#include "GLContext.h"
+#include "Log.h"
+
+namespace crown
+{
+
+extern ANativeWindow* g_android_window;
+
+//-----------------------------------------------------------------------------
+static const char* egl_error_to_string(EGLint error)
+{
+	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";
+	}
+}
+
+//-----------------------------------------------------------------------------
+#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()
+{
+    const EGLint attrib_list[] = {
+            EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
+            EGL_BLUE_SIZE, 8,
+            EGL_GREEN_SIZE, 8,
+            EGL_RED_SIZE, 8,
+            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");
+
+	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");
+
+	Log::d("EGL Initialized: major = %d, minor = %d", egl_major, egl_minor);
+
+	EGLBoolean bind_success = EGL_CHECK(eglBindAPI(EGL_OPENGL_ES_API));
+	CE_ASSERT(bind_success != EGL_FALSE, "Failed to bind OpenGL|ES API");
+
+	EGLBoolean cfg_success = EGL_CHECK(eglChooseConfig(display, attrib_list, &config, 1, &num_configs));
+	CE_ASSERT(cfg_success == EGL_TRUE, "Failed to choose EGL configuration");
+
+	EGLint format;
+	EGL_CHECK(eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &format));
+
+	ANativeWindow_setBuffersGeometry(g_android_window, 0, 0, format);
+
+	context = EGL_CHECK(eglCreateContext(display, config, EGL_NO_CONTEXT, attributes));
+	CE_ASSERT(context != EGL_NO_CONTEXT, "Oops, failed to create EGL context");
+
+	surface = EGL_CHECK(eglCreateWindowSurface(display, config, (EGLNativeWindowType)g_android_window, NULL));
+	CE_ASSERT(surface != EGL_NO_SURFACE, "Oops, failed to create EGL surface");
+
+	EGL_CHECK(eglMakeCurrent(display, surface, surface, context));
+
+	Log::d("EGL context created");
+}
+
+//-----------------------------------------------------------------------------
+void GLContext::destroy_context()
+{
+	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()
+{
+	EGL_CHECK(eglMakeCurrent(display, surface, surface, context));
+	EGL_CHECK(eglSwapBuffers(display, surface));
+}
+
+}

+ 9 - 7
engine/renderers/gles/egl/GLContext.h → 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:
@@ -44,14 +41,19 @@ public:
 
 	void			swap_buffers();
 
+	bool is_valid()
+	{
+		return display != EGL_NO_DISPLAY;
+	}
+
 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

+ 3 - 1
engine/renderers/gl/glx/GLContext.cpp

@@ -42,7 +42,7 @@ void set_x11_display_and_window(Display* dpy, Window win)
 
 //-----------------------------------------------------------------------------
 GLContext::GLContext() :
-	m_glx_context(NULL)
+	m_glx_context(None)
 {
 }
 
@@ -91,6 +91,8 @@ void GLContext::destroy_context()
 			glXDestroyContext(s_x11_display, m_glx_context);
 		}
 	}
+
+	m_glx_context = None;
 }
 
 //-----------------------------------------------------------------------------

+ 6 - 1
engine/renderers/gl/glx/GLContext.h

@@ -46,9 +46,14 @@ public:
 
 	void			swap_buffers();
 
+	bool is_valid()
+	{
+		return m_glx_context != None;
+	}
+
 private:
 
-	GLXContext		m_glx_context;
+	GLXContext m_glx_context;
 };
 
 } // namespace crown

+ 0 - 972
engine/renderers/gles/GLESRenderer.cpp

@@ -1,972 +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 "Config.h"
-
-#include <GLES2/gl2.h>
-#include <algorithm>
-
-#include "Assert.h"
-#include "Types.h"
-#include "GLESRenderer.h"
-#include "GLESUtils.h"
-#include "Log.h"
-#include "Material.h"
-#include "Vec2.h"
-#include "Vec3.h"
-#include "Vec4.h"
-#include "Mat3.h"
-#include "Mat4.h"
-#include "Device.h"
-#include "ResourceManager.h"
-
-namespace crown
-{
-
-//-----------------------------------------------------------------------------
-static const char* gl_error_to_string(GLenum error)
-{
-	switch (error)
-	{
-		case GL_INVALID_ENUM: return "GL_INVALID_ENUM";
-		case GL_INVALID_VALUE: return "GL_INVALID_VALUE";
-		case GL_INVALID_OPERATION: return "GL_INVALID_OPERATION";
-		case GL_OUT_OF_MEMORY: return "GL_OUT_OF_MEMORY";
-		default: return "UNKNOWN_GL_ERROR";
-	}
-}
-
-//-----------------------------------------------------------------------------
-#ifdef CROWN_DEBUG
-	#define GL_CHECK(function)\
-		function;\
-		do { GLenum error; CE_ASSERT((error = glGetError()) == GL_NO_ERROR,\
-				"OpenGL error: %s", gl_error_to_string(error)); } while (0)
-#else
-	#define GL_CHECK(function)\
-		function;
-#endif
-
-//-----------------------------------------------------------------------------
-GLESRenderer::GLESRenderer() :
-	m_max_texture_size(0),
-	m_max_texture_units(0),
-	m_max_vertex_indices(0),
-	m_max_vertex_vertices(0),
-	m_max_anisotropy(0.0f),
-
-	m_ambient_light_color(Color4::GRAY),
-
-	m_textures_id_table(m_allocator, MAX_TEXTURES),
-	m_active_texture_unit(0),
-
-	m_vertex_buffers_id_table(m_allocator, MAX_VERTEX_BUFFERS),
-	m_index_buffers_id_table(m_allocator, MAX_INDEX_BUFFERS),
-	m_vertex_shaders_id_table(m_allocator, MAX_VERTEX_SHADERS),
-	m_pixel_shaders_id_table(m_allocator, MAX_PIXEL_SHADERS),
-	m_gpu_programs_id_table(m_allocator, 128)
-	//m_render_buffers_id_table(m_allocator, MAX_RENDER_BUFFERS)
-{
-	m_min_max_point_size[0] = 0.0f;
-	m_min_max_point_size[1] = 0.0f;
-	m_min_max_line_width[0] = 0.0f;
-	m_min_max_line_width[1] = 0.0f;
-
-	// Initialize viewport and scissor
-	m_viewport[0] = 0;
-	m_viewport[1] = 0;
-	m_viewport[2] = 0;
-	m_viewport[3] = 0;
-
-	m_scissor[0] = 0;
-	m_scissor[1] = 0;
-	m_scissor[2] = 0;
-	m_scissor[3] = 0;
-
-	// Initialize texture units
-	for (uint32_t i = 0; i < MAX_TEXTURE_UNITS; i++)
-	{
-		m_texture_unit[i] = 0;
-		m_texture_unit_target[i] = GL_TEXTURE_2D;
-	}
-
-	// Initialize the matrices
-	for (uint32_t i = 0; i < MT_COUNT; i++)
-	{
-		m_matrix[i].load_identity();
-	}
-
-	m_model_view_matrix.load_identity();
-	m_model_view_projection_matrix.load_identity();
-}
-
-//-----------------------------------------------------------------------------
-GLESRenderer::~GLESRenderer()
-{
-}
-
-//-----------------------------------------------------------------------------
-void GLESRenderer::init()
-{
-	m_context.create_context();
-
-	GL_CHECK(glGetIntegerv(GL_MAX_TEXTURE_SIZE, &m_max_texture_size));
-	GL_CHECK(glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &m_max_texture_units));
-	//glGetIntegerv(GL_MAX_ELEMENTS_INDICES, &m_max_vertex_indices);
-	//glGetIntegerv(GL_MAX_ELEMENTS_VERTICES, &m_max_vertex_vertices);
-
-
-	GL_CHECK(glGetFloatv(GL_ALIASED_POINT_SIZE_RANGE, &m_min_max_point_size[0]));
-	//glGetFloatv(GL_LINE_WIDTH_RANGE, &m_min_max_line_width[0]);
-
-	Log::i("OpenGL Vendor\t: %s", glGetString(GL_VENDOR));
-	Log::i("OpenGL Renderer\t: %s", glGetString(GL_RENDERER));
-	Log::i("OpenGL Version\t: %s", glGetString(GL_VERSION));
-
-	Log::d("Min Point Size\t: %f", m_min_max_point_size[0]);
-	Log::d("Max Point Size\t: %f", m_min_max_point_size[1]);
-	Log::d("Min Line Width\t: %f", m_min_max_line_width[0]);
-	Log::d("Max Line Width\t: %f", m_min_max_line_width[1]);
-	Log::d("Max Texture Size\t: %dx%d", m_max_texture_size, m_max_texture_size);
-	Log::d("Max Texture Units\t: %d", m_max_texture_units);
-	Log::d("Max Vertex Indices\t: %d", m_max_vertex_indices);
-	Log::d("Max Vertex Vertices\t: %d", m_max_vertex_vertices);
-	Log::d("Max Anisotropy\t: %f", m_max_anisotropy);
-
-	GL_CHECK(glDisable(GL_BLEND));
-	GL_CHECK(glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA));
-	GL_CHECK(glBlendEquation(GL_FUNC_ADD));
-
-	GL_CHECK(glFrontFace(GL_CCW));
-	GL_CHECK(glEnable(GL_CULL_FACE));
-
-	// Set the default framebuffer clear color
-	GL_CHECK(glClearColor(0.5f, 0.5f, 0.5f, 0.5f));
-
-	// Enable depth test
-	GL_CHECK(glEnable(GL_DEPTH_TEST));
-	GL_CHECK(glDepthFunc(GL_LEQUAL));
-	GL_CHECK(glClearDepthf(1.0));
-
-	// Enable scissor test
-	GL_CHECK(glEnable(GL_SCISSOR_TEST));
-
-	// Disable dithering
-	GL_CHECK(glDisable(GL_DITHER));
-
-	Log::i("OpenGL Renderer initialized.");
-
-	load_default_shaders();
-}
-
-//-----------------------------------------------------------------------------
-void GLESRenderer::shutdown()
-{
-	unload_default_shaders();
-
-	m_context.destroy_context();
-}
-
-//-----------------------------------------------------------------------------
-VertexBufferId GLESRenderer::create_vertex_buffer(size_t count, VertexFormat format, const void* vertices)
-{
-	const VertexBufferId id = m_vertex_buffers_id_table.create();
-
-	VertexBuffer& buffer = m_vertex_buffers[id.index];
-
-	GL_CHECK(glGenBuffers(1, &buffer.gl_object));
-
-	GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER, buffer.gl_object));
-	GL_CHECK(glBufferData(GL_ARRAY_BUFFER, count * Vertex::bytes_per_vertex(format), vertices, GL_STATIC_DRAW));
-
-	buffer.count = count;
-	buffer.format = format;
-
-	return id;
-}
-
-//-----------------------------------------------------------------------------
-VertexBufferId GLESRenderer::create_dynamic_vertex_buffer(size_t count, VertexFormat format, const void* vertices)
-{
-	const VertexBufferId id = m_vertex_buffers_id_table.create();
-
-	VertexBuffer& buffer = m_vertex_buffers[id.index];
-
-	GL_CHECK(glGenBuffers(1, &buffer.gl_object));
-
-	GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER, buffer.gl_object));
-	GL_CHECK(glBufferData(GL_ARRAY_BUFFER, count * Vertex::bytes_per_vertex(format), vertices, GL_STREAM_DRAW));
-
-	buffer.count = count;
-	buffer.format = format;
-
-	return id;
-}
-
-//-----------------------------------------------------------------------------
-void GLESRenderer::update_vertex_buffer(VertexBufferId id, size_t offset, size_t count, const void* vertices)
-{
-	CE_ASSERT(m_vertex_buffers_id_table.has(id), "Vertex buffer does not exist");
-
-	VertexBuffer& buffer = m_vertex_buffers[id.index];
-
-	GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER, buffer.gl_object));
-	GL_CHECK(glBufferSubData(GL_ARRAY_BUFFER, offset * Vertex::bytes_per_vertex(buffer.format),
-					count * Vertex::bytes_per_vertex(buffer.format), vertices));
-}
-
-//-----------------------------------------------------------------------------
-void GLESRenderer::destroy_vertex_buffer(VertexBufferId id)
-{
-	CE_ASSERT(m_vertex_buffers_id_table.has(id), "Vertex buffer does not exist");
-
-	VertexBuffer& buffer = m_vertex_buffers[id.index];
-
-	GL_CHECK(glDeleteBuffers(1, &buffer.gl_object));
-
-	m_vertex_buffers_id_table.destroy(id);
-}
-
-//-----------------------------------------------------------------------------
-IndexBufferId GLESRenderer::create_index_buffer(size_t count, const void* indices)
-{
-	const IndexBufferId id = m_index_buffers_id_table.create();
-
-	IndexBuffer& buffer = m_index_buffers[id.index];
-
-	GL_CHECK(glGenBuffers(1, &buffer.gl_object));
-
-	GL_CHECK(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer.gl_object));
-	GL_CHECK(glBufferData(GL_ELEMENT_ARRAY_BUFFER, count * sizeof(GLushort), indices, GL_STATIC_DRAW));
-
-	buffer.index_count = count;
-
-	return id;
-}
-
-//-----------------------------------------------------------------------------
-void GLESRenderer::destroy_index_buffer(IndexBufferId id)
-{
-	CE_ASSERT(m_index_buffers_id_table.has(id), "Index buffer does not exist");
-
-	IndexBuffer& buffer = m_index_buffers[id.index];
-
-	GL_CHECK(glDeleteBuffers(1, &buffer.gl_object));
-
-	m_index_buffers_id_table.destroy(id);
-}
-
-//-----------------------------------------------------------------------------
-TextureId GLESRenderer::create_texture(uint32_t width, uint32_t height, PixelFormat format, const void* data)
-{
-	const TextureId id = m_textures_id_table.create();
-
-	Texture& gl_texture = m_textures[id.index];
-
-	GL_CHECK(glGenTextures(1, &gl_texture.gl_object));
-
-	GL_CHECK(glBindTexture(GL_TEXTURE_2D, gl_texture.gl_object));
-
-	//GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE));
-
-	// FIXME
-	GL_CHECK(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0,
-				 GLES::pixel_format(format), GL_UNSIGNED_BYTE, data));
-
-	gl_texture.format = format;
-
-	return id;
-}
-
-//-----------------------------------------------------------------------------
-void GLESRenderer::update_texture(TextureId id, uint32_t x, uint32_t y, uint32_t width, uint32_t height, const void* data)
-{
-	CE_ASSERT(m_textures_id_table.has(id), "Texture does not exist");
-
-	Texture& gl_texture = m_textures[id.index];
-
-	GL_CHECK(glBindTexture(GL_TEXTURE_2D, gl_texture.gl_object));
-
-	GL_CHECK(glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, width, height, GLES::pixel_format(gl_texture.format),
-					GL_UNSIGNED_BYTE, data));
-}
-
-//-----------------------------------------------------------------------------
-void GLESRenderer::destroy_texture(TextureId id)
-{
-	CE_ASSERT(m_textures_id_table.has(id), "Texture does not exist");
-
-	Texture& gl_texture = m_textures[id.index];
-
-	GL_CHECK(glDeleteTextures(1, &gl_texture.gl_object));
-}
-
-//-----------------------------------------------------------------------------
-VertexShaderId GLESRenderer::create_vertex_shader(const char* program)
-{
-	CE_ASSERT(program != NULL, "Program must be != NULL");
-
-	const VertexShaderId& id = m_vertex_shaders_id_table.create();
-
-	VertexShader& gl_shader = m_vertex_shaders[id.index];
-
-	gl_shader.gl_object = GL_CHECK(glCreateShader(GL_VERTEX_SHADER));
-
-	GL_CHECK(glShaderSource(gl_shader.gl_object, 1, &program, NULL));
-
-	GL_CHECK(glCompileShader(gl_shader.gl_object));
-
-	GLint success;
-	GL_CHECK(glGetShaderiv(gl_shader.gl_object, GL_COMPILE_STATUS, &success));
-
-	if (!success)
-	{
-		GLchar info_log[256];
-
-		GL_CHECK(glGetShaderInfoLog(gl_shader.gl_object, 256, NULL, info_log));
-
-		Log::e("Vertex shader compilation failed.");
-		Log::e("Log: %s", info_log);
-		CE_ASSERT(0, "");
-	}
-
-	return id;
-}
-
-//-----------------------------------------------------------------------------
-void GLESRenderer::destroy_vertex_shader(VertexShaderId id)
-{
-	CE_ASSERT(m_vertex_shaders_id_table.has(id), "Vertex shader does not exist");
-
-	VertexShader& gl_shader = m_vertex_shaders[id.index];
-
-	GL_CHECK(glDeleteShader(gl_shader.gl_object));
-}
-
-//-----------------------------------------------------------------------------
-PixelShaderId GLESRenderer::create_pixel_shader(const char* program)
-{
-	CE_ASSERT(program != NULL, "Program must be != NULL");
-
-	const PixelShaderId& id = m_pixel_shaders_id_table.create();
-
-	PixelShader& gl_shader = m_pixel_shaders[id.index];
-
-	gl_shader.gl_object = GL_CHECK(glCreateShader(GL_FRAGMENT_SHADER));
-
-	GL_CHECK(glShaderSource(gl_shader.gl_object, 1, &program, NULL));
-
-	GL_CHECK(glCompileShader(gl_shader.gl_object));
-
-	GLint success;
-	GL_CHECK(glGetShaderiv(gl_shader.gl_object, GL_COMPILE_STATUS, &success));
-
-	if (!success)
-	{
-		GLchar info_log[256];
-
-		GL_CHECK(glGetShaderInfoLog(gl_shader.gl_object, 256, NULL, info_log));
-
-		Log::e("Pixel shader compilation failed.");
-		Log::e("Log: %s", info_log);
-		CE_ASSERT(0, "");
-	}
-
-	return id;	
-}
-
-//-----------------------------------------------------------------------------
-void GLESRenderer::destroy_pixel_shader(PixelShaderId id)
-{
-	CE_ASSERT(m_pixel_shaders_id_table.has(id), "Pixel shader does not exist");
-
-	PixelShader& gl_shader = m_pixel_shaders[id.index];
-
-	GL_CHECK(glDeleteShader(gl_shader.gl_object));	
-}
-
-//-----------------------------------------------------------------------------
-GPUProgramId GLESRenderer::create_gpu_program(VertexShaderId vs, PixelShaderId ps)
-{
-	CE_ASSERT(m_vertex_shaders_id_table.has(vs), "Vertex shader does not exist");
-	CE_ASSERT(m_pixel_shaders_id_table.has(ps), "Pixel shader does not exist");
-
-	const GPUProgramId id = m_gpu_programs_id_table.create();
-
-	GPUProgram& gl_program = m_gpu_programs[id.index];
-
-	gl_program.gl_object = GL_CHECK(glCreateProgram());
-
-	GL_CHECK(glAttachShader(gl_program.gl_object, m_vertex_shaders[id.index].gl_object));
-	GL_CHECK(glAttachShader(gl_program.gl_object, m_pixel_shaders[id.index].gl_object));
-
-	GL_CHECK(glBindAttribLocation(gl_program.gl_object, SA_VERTEX, "vertex"));
-	GL_CHECK(glBindAttribLocation(gl_program.gl_object, SA_COORDS, "coords"));
-	GL_CHECK(glBindAttribLocation(gl_program.gl_object, SA_NORMAL, "normal"));
-
-	GL_CHECK(glLinkProgram(gl_program.gl_object));
-
-	GLint success;
-	GL_CHECK(glGetProgramiv(gl_program.gl_object, GL_LINK_STATUS, &success));
-
-	if (!success)
-	{
-		GLchar info_log[256];
-		GL_CHECK(glGetProgramInfoLog(gl_program.gl_object, 256, NULL, info_log));
-		Log::e("GPU program compilation failed.\n");
-		Log::e("Log: %s", info_log);
-	}
-
-	return id;
-}
-
-//-----------------------------------------------------------------------------
-void GLESRenderer::destroy_gpu_program(GPUProgramId id)
-{
-	CE_ASSERT(m_gpu_programs_id_table.has(id), "GPU program does not exist");
-
-	GPUProgram& gl_program = m_gpu_programs[id.index];
-
-	GL_CHECK(glDeleteProgram(gl_program.gl_object));
-}
-
-//-----------------------------------------------------------------------------
-void GLESRenderer::set_gpu_program_bool_uniform(GPUProgramId id, const char* name, bool value)
-{
-	CE_ASSERT(m_gpu_programs_id_table.has(id), "GPU program does not exist");
-
-	const GLint uniform = find_gpu_program_uniform(m_gpu_programs[id.index].gl_object, name);
-
-	GL_CHECK(glUniform1i(uniform, (GLint) value));
-}
-
-//-----------------------------------------------------------------------------
-void GLESRenderer::set_gpu_program_int_uniform(GPUProgramId id, const char* name, int value)
-{
-	CE_ASSERT(m_gpu_programs_id_table.has(id), "GPU program does not exist");
-
-	const GLint uniform = find_gpu_program_uniform(m_gpu_programs[id.index].gl_object, name);
-
-	GL_CHECK(glUniform1i(uniform, (GLint) value));
-}
-
-//-----------------------------------------------------------------------------
-void GLESRenderer::set_gpu_program_vec2_uniform(GPUProgramId id, const char* name, const Vec2& value)
-{
-	CE_ASSERT(m_gpu_programs_id_table.has(id), "GPU program does not exist");
-
-	const GLint uniform = find_gpu_program_uniform(m_gpu_programs[id.index].gl_object, name);
-
-	GL_CHECK(glUniform2fv(uniform, 1, value.to_float_ptr()));
-}
-
-//-----------------------------------------------------------------------------
-void GLESRenderer::set_gpu_program_vec3_uniform(GPUProgramId id, const char* name, const Vec3& value)
-{
-	CE_ASSERT(m_gpu_programs_id_table.has(id), "GPU program does not exist");
-
-	const GLint uniform = find_gpu_program_uniform(m_gpu_programs[id.index].gl_object, name);
-
-	GL_CHECK(glUniform3fv(uniform, 1, value.to_float_ptr()));
-}
-
-//-----------------------------------------------------------------------------
-void GLESRenderer::set_gpu_program_vec4_uniform(GPUProgramId id, const char* name, const Vec4& value)
-{
-	CE_ASSERT(m_gpu_programs_id_table.has(id), "GPU program does not exist");
-
-	const GLint uniform = find_gpu_program_uniform(m_gpu_programs[id.index].gl_object, name);
-
-	GL_CHECK(glUniform4fv(uniform, 1, value.to_float_ptr()));
-}
-
-//-----------------------------------------------------------------------------
-void GLESRenderer::set_gpu_porgram_mat3_uniform(GPUProgramId id, const char* name, const Mat3& value)
-{
-	CE_ASSERT(m_gpu_programs_id_table.has(id), "GPU program does not exist");
-
-	const GLint uniform = find_gpu_program_uniform(m_gpu_programs[id.index].gl_object, name);
-
-	GL_CHECK(glUniformMatrix3fv(uniform, 1, GL_FALSE, value.to_float_ptr()));
-}
-
-//-----------------------------------------------------------------------------
-void GLESRenderer::set_gpu_program_mat4_uniform(GPUProgramId id, const char* name, const Mat4& value)
-{
-	CE_ASSERT(m_gpu_programs_id_table.has(id), "GPU program does not exist");
-
-	const GLint uniform = find_gpu_program_uniform(m_gpu_programs[id.index].gl_object, name);
-
-	GL_CHECK(glUniformMatrix4fv(uniform, 1, GL_FALSE, value.to_float_ptr()));
-}
-
-//-----------------------------------------------------------------------------
-void GLESRenderer::set_gpu_program_sampler_uniform(GPUProgramId id, const char* name, uint32_t value)
-{
-	CE_ASSERT(m_gpu_programs_id_table.has(id), "GPU program does not exist");
-
-	const GLint uniform = find_gpu_program_uniform(m_gpu_programs[id.index].gl_object, name);
-
-	GL_CHECK(glUniform1i(uniform, (GLint) value));	
-}
-
-//-----------------------------------------------------------------------------
-void GLESRenderer::bind_gpu_program(GPUProgramId id) const
-{
-	CE_ASSERT(m_gpu_programs_id_table.has(id), "GPU program does not exist");
-
-	const GPUProgram& gl_program = m_gpu_programs[id.index];
-
-	GL_CHECK(glUseProgram(gl_program.gl_object));
-}
-
-//-----------------------------------------------------------------------------
-void GLESRenderer::set_clear_color(const Color4& color)
-{
-	GL_CHECK(glClearColor(color.r, color.g, color.b, color.a));
-}
-
-//-----------------------------------------------------------------------------
-void GLESRenderer::set_ambient_light(const Color4& color)
-{
-	m_ambient_light_color = color;
-}
-
-//-----------------------------------------------------------------------------
-void GLESRenderer::bind_texture(uint32_t unit, TextureId texture)
-{
-	CE_ASSERT(m_textures_id_table.has(texture), "Texture does not exist");
-
-	if (!activate_texture_unit(unit))
-	{
-		return;
-	}
-
-	m_texture_unit_target[unit] = GL_TEXTURE_2D;
-	m_texture_unit[unit] = m_textures[texture.index].gl_object;
-
-	GL_CHECK(glEnable(m_texture_unit_target[unit]));
-	GL_CHECK(glBindTexture(m_texture_unit_target[unit], m_texture_unit[unit]));
-}
-
-//-----------------------------------------------------------------------------
-void GLESRenderer::set_texturing(uint32_t unit, bool texturing)
-{
-	if (!activate_texture_unit(unit))
-		return;
-
-	if (texturing)
-	{
-		GL_CHECK(glEnable(m_texture_unit_target[unit]));
-	}
-	else
-	{
-		GL_CHECK(glDisable(m_texture_unit_target[unit]));
-	}
-}
-
-//-----------------------------------------------------------------------------
-void GLESRenderer::set_texture_wrap(uint32_t unit, TextureWrap wrap)
-{
-	GLenum gl_wrap = GLES::texture_wrap(wrap);
-
-	GL_CHECK(glTexParameteri(m_texture_unit_target[unit], GL_TEXTURE_WRAP_S, gl_wrap));
-	GL_CHECK(glTexParameteri(m_texture_unit_target[unit], GL_TEXTURE_WRAP_T, gl_wrap));
-}
-
-//-----------------------------------------------------------------------------
-void GLESRenderer::set_texture_filter(uint32_t unit, TextureFilter filter)
-{
-	if (!activate_texture_unit(unit))
-		return;
-
-	GLint min_filter;
-	GLint mag_filter;
-
-	GLES::texture_filter(filter, min_filter, mag_filter);
-
-	GL_CHECK(glTexParameteri(m_texture_unit_target[unit], GL_TEXTURE_MIN_FILTER, min_filter));
-	GL_CHECK(glTexParameteri(m_texture_unit_target[unit], GL_TEXTURE_MAG_FILTER, mag_filter));
-}
-
-//-----------------------------------------------------------------------------
-void GLESRenderer::set_backface_culling(bool culling)
-{
-	if (culling)
-	{
-		GL_CHECK(glEnable(GL_CULL_FACE));
-	}
-	else
-	{
-		GL_CHECK(glDisable(GL_CULL_FACE));
-	}
-}
-
-//-----------------------------------------------------------------------------
-void GLESRenderer::set_depth_test(bool test)
-{
-	if (test)
-	{
-		GL_CHECK(glEnable(GL_DEPTH_TEST));
-	}
-	else
-	{
-		GL_CHECK(glDisable(GL_DEPTH_TEST));
-	}
-}
-
-//-----------------------------------------------------------------------------
-void GLESRenderer::set_depth_write(bool write)
-{
-	GL_CHECK(glDepthMask((GLboolean) write));
-}
-
-//-----------------------------------------------------------------------------
-void GLESRenderer::set_depth_func(CompareFunction func)
-{
-	GLenum gl_func = GLES::compare_function(func);
-
-	GL_CHECK(glDepthFunc(gl_func));
-}
-
-//-----------------------------------------------------------------------------
-void GLESRenderer::set_blending(bool blending)
-{
-	if (blending)
-	{
-		GL_CHECK(glEnable(GL_BLEND));
-	}
-	else
-	{
-		GL_CHECK(glDisable(GL_BLEND));
-	}
-}
-
-//-----------------------------------------------------------------------------
-void GLESRenderer::set_blending_params(BlendEquation equation, BlendFunction src, BlendFunction dst, const Color4& color)
-{
-	GLenum gl_equation = GLES::blend_equation(equation);
-
-	GL_CHECK(glBlendEquation(gl_equation));
-
-	GLenum gl_src_factor = GLES::blend_function(src);
-	GLenum gl_dst_factor = GLES::blend_function(dst);
-
-	GL_CHECK(glBlendFunc(gl_src_factor, gl_dst_factor));
-
-	GL_CHECK(glBlendColor(color.r, color.g, color.b, color.a));
-}
-
-//-----------------------------------------------------------------------------
-void GLESRenderer::set_color_write(bool write)
-{
-	if (write)
-	{
-		GL_CHECK(glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE));
-	}
-	else
-	{
-		GL_CHECK(glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE));
-	}
-}
-
-//-----------------------------------------------------------------------------
-void GLESRenderer::set_front_face(FrontFace face)
-{
-	const GLenum gl_face = (face == FF_CCW) ? GL_CCW : GL_CW;
-
-	GL_CHECK(glFrontFace(gl_face));
-}
-
-//-----------------------------------------------------------------------------
-void GLESRenderer::set_viewport_params(int32_t x, int32_t y, int32_t width, int32_t height)
-{
-	m_viewport[0] = x;
-	m_viewport[1] = y;
-	m_viewport[2] = width;
-	m_viewport[3] = height;
-
-	GL_CHECK(glViewport(x, y, width, height));
-}
-
-//-----------------------------------------------------------------------------
-void GLESRenderer::get_viewport_params(int32_t& x, int32_t& y, int32_t& width, int32_t& height)
-{
-	x = m_viewport[0];
-	y = m_viewport[1];
-	width = m_viewport[2];
-	height = m_viewport[3];
-}
-
-//-----------------------------------------------------------------------------
-void GLESRenderer::set_scissor(bool scissor)
-{
-	if (scissor)
-	{
-		GL_CHECK(glEnable(GL_SCISSOR_TEST));
-	}
-	else
-	{
-		GL_CHECK(glDisable(GL_SCISSOR_TEST));
-	}
-}
-
-//-----------------------------------------------------------------------------
-void GLESRenderer::set_scissor_params(int32_t x, int32_t y, int32_t width, int32_t height)
-{
-	m_scissor[0] = x;
-	m_scissor[1] = y;
-	m_scissor[2] = width;
-	m_scissor[3] = height;
-
-	GL_CHECK(glScissor(x, y, width, height));
-}
-
-//-----------------------------------------------------------------------------
-void GLESRenderer::get_scissor_params(int32_t& x, int32_t& y, int32_t& width, int32_t& height)
-{
-	x = m_scissor[0];
-	y = m_scissor[1];
-	width = m_scissor[2];
-	height = m_scissor[3];
-}
-
-//-----------------------------------------------------------------------------
-void GLESRenderer::frame()
-{
-	// Clear frame/depth buffer
-	GL_CHECK(glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT));
-
-	// Bind the default gpu program
-	bind_gpu_program(m_default_gpu_program);
-
-	set_gpu_program_mat4_uniform(m_default_gpu_program, "mvp_matrix", m_model_view_projection_matrix);
-
-	GL_CHECK(glFinish());
-
-	m_context.swap_buffers();
-}
-
-//-----------------------------------------------------------------------------
-Mat4 GLESRenderer::get_matrix(MatrixType type) const
-{
-	return m_matrix[type];
-}
-
-//-----------------------------------------------------------------------------
-void GLESRenderer::set_matrix(MatrixType type, const Mat4& matrix)
-{
-	m_matrix[type] = matrix;
-
-	switch (type)
-	{
-		case MT_VIEW:
-		case MT_MODEL:
-		{
-			m_model_view_matrix = m_matrix[MT_VIEW] * m_matrix[MT_MODEL];
-			break;
-		}
-		case MT_PROJECTION:
-		{
-			m_model_view_projection_matrix =  m_matrix[MT_PROJECTION] * m_model_view_matrix;
-			break;
-		}
-		default:
-		{
-			break;
-			CE_ASSERT(0, "");
-		}
-	}
-}
-
-//-----------------------------------------------------------------------------
-void GLESRenderer::bind_vertex_buffer(VertexBufferId vb) const
-{
-	CE_ASSERT(m_vertex_buffers_id_table.has(vb), "Vertex buffer does not exist");
-
-	const VertexBuffer& vertex_buffer = m_vertex_buffers[vb.index];
-
-	GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer.gl_object));
-
-	switch (vertex_buffer.format)
-	{
-		case VF_XY_FLOAT_32:
-		{
-			GL_CHECK(glEnableVertexAttribArray(SA_VERTEX));
-			GL_CHECK(glVertexAttribPointer(SA_VERTEX, 2, GL_FLOAT, GL_FALSE, 0, 0));
-			break;
-		}
-		case VF_XYZ_FLOAT_32:
-		{
-			GL_CHECK(glEnableVertexAttribArray(SA_VERTEX));
-			GL_CHECK(glVertexAttribPointer(SA_VERTEX, 3, GL_FLOAT, GL_FALSE, 0, 0));
-			break;
-		}
-		case VF_UV_FLOAT_32:
-		{
-			GL_CHECK(glEnableVertexAttribArray(SA_COORDS));
-			GL_CHECK(glVertexAttribPointer(SA_COORDS, 2, GL_FLOAT, GL_FALSE, 0, 0));
-			break;
-		}
-		case VF_UVT_FLOAT_32:
-		{
-			GL_CHECK(glEnableVertexAttribArray(SA_COORDS));
-			GL_CHECK(glVertexAttribPointer(SA_COORDS, 3, GL_FLOAT, GL_FALSE, 0, 0));
-			break;
-		}
-		case VF_XYZ_NORMAL_FLOAT_32:
-		{
-			GL_CHECK(glEnableVertexAttribArray(SA_NORMAL));
-			GL_CHECK(glVertexAttribPointer(SA_NORMAL, 3, GL_FLOAT, GL_FALSE, 0, 0));
-			break;
-		}
-		case VF_XYZ_UV_XYZ_NORMAL_FLOAT_32:
-		{
-			break;
-		}
-		default:
-		{
-			CE_ASSERT(0, "Vertex format unknown");
-			break;
-		}
-	}
-}
-
-//-----------------------------------------------------------------------------
-void GLESRenderer::draw_triangles(IndexBufferId id) const
-{
-	CE_ASSERT(m_index_buffers_id_table.has(id), "Index buffer does not exist");
-
-	const IndexBuffer& index_buffer = m_index_buffers[id.index];
-
-	GL_CHECK(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer.gl_object));
-
-	GL_CHECK(glDrawElements(GL_TRIANGLES, index_buffer.index_count, GL_UNSIGNED_SHORT, 0));
-}
-
-//-----------------------------------------------------------------------------
-// void GLESRenderer::bind_render_buffer(RenderBufferId id) const
-// {
-// 	CE_ASSERT(m_render_buffers_id_table.has(id), "Render buffer does not exist");
-
-// 	const GLRenderBuffer& render_buffer = m_render_buffers[id.index];
-// }
-
-//-----------------------------------------------------------------------------
-void GLESRenderer::draw_lines(const float* vertices, const float* colors, uint32_t count)
-{
-	// GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER, 0));
-	// GL_CHECK(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
-
-	// GL_CHECK(glEnableClientState(GL_VERTEX_ARRAY));
-	// GL_CHECK(glEnableClientState(GL_COLOR_ARRAY));
-
-	// GL_CHECK(glVertexPointer(3, GL_FLOAT, 0, vertices));
-	// GL_CHECK(glColorPointer(4, GL_FLOAT, 0, colors));
-
-	// GL_CHECK(glDrawArrays(GL_LINES, 0, count));
-
-	// GL_CHECK(glDisableClientState(GL_COLOR_ARRAY));
-	// GL_CHECK(glDisableClientState(GL_VERTEX_ARRAY));
-}
-
-//-----------------------------------------------------------------------------
-void GLESRenderer::load_default_shaders()
-{
-	static const char* vs_text =
-		"attribute vec4 vertex;"
-		"attribute vec2 coords;"
-		"uniform mat4 mvp_matrix;"
-
-		"void main(void)"
-		"{"
-		"	gl_Position = mvp_matrix * vertex;"
-		"}";
-
-	static const char* ps_text = 
-		"void main(void)"
-		"{"
-		"	gl_FragColor = vec4(1, 0, 0, 0);"
-		"}";
-
-	m_default_vertex_shader = create_vertex_shader(vs_text);
-	m_default_pixel_shader = create_pixel_shader(ps_text);
-
-	// Create and bind the default program
-	m_default_gpu_program = create_gpu_program(m_default_vertex_shader, m_default_pixel_shader);
-}
-
-//-----------------------------------------------------------------------------
-void GLESRenderer::unload_default_shaders()
-{
-	destroy_pixel_shader(m_default_pixel_shader);
-	destroy_vertex_shader(m_default_vertex_shader);
-
-	destroy_gpu_program(m_default_gpu_program);
-}
-
-//-----------------------------------------------------------------------------
-void GLESRenderer::reload_default_shaders()
-{
-}
-
-//-----------------------------------------------------------------------------
-bool GLESRenderer::activate_texture_unit(uint32_t unit)
-{
-	if (unit >= (uint32_t) m_max_texture_units)
-	{
-		return false;
-	}
-
-	GL_CHECK(glActiveTexture(GL_TEXTURE0 + unit));
-	m_active_texture_unit = unit;
-
-	return true;
-}
-
-//-----------------------------------------------------------------------------
-GLint GLESRenderer::find_gpu_program_uniform(GLuint program, const char* name) const
-{
-	GLint uniform = GL_CHECK(glGetUniformLocation(program, name));
-
-	CE_ASSERT(uniform != -1, "Uniform does not exist");
-
-	return uniform;
-}
-
-//-----------------------------------------------------------------------------
-Renderer* Renderer::create(Allocator& a)
-{
-	return CE_NEW(a, GLESRenderer);
-}
-
-//-----------------------------------------------------------------------------
-void Renderer::destroy(Allocator& a, Renderer* renderer)
-{
-	CE_DELETE(a, renderer);
-}
-
-} // namespace crown

+ 0 - 276
engine/renderers/gles/GLESRenderer.h

@@ -1,276 +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.
-*/
-
-#pragma once
-
-#include <GLES2/gl2.h>
-
-#include "Renderer.h"
-#include "Texture.h"
-#include "VertexBuffer.h"
-#include "IndexBuffer.h"
-#include "RenderBuffer.h"
-#include "VertexShader.h"
-#include "PixelShader.h"
-#include "IdTable.h"
-#include "HeapAllocator.h"
-#include "Resource.h"
-#include "GLContext.h"
-
-namespace crown
-{
-
-const uint32_t MAX_TEXTURE_UNITS = 8;
-
-//-----------------------------------------------------------------------------
-struct Texture
-{
-	GLuint				gl_object;
-	PixelFormat			format;
-};
-
-//-----------------------------------------------------------------------------
-struct VertexBuffer
-{
-	GLuint				gl_object;
-	size_t				count;
-	VertexFormat		format;
-};
-
-//-----------------------------------------------------------------------------
-struct IndexBuffer
-{
-	GLuint				gl_object;
-	uint32_t			index_count;
-};
-
-//-----------------------------------------------------------------------------
-struct RenderBuffer
-{
-	GLuint				gl_frame_buffer;
-	GLuint				gl_render_buffer;
-};
-
-//-----------------------------------------------------------------------------
-struct VertexShader
-{
-	GLuint				gl_object;
-};
-
-//-----------------------------------------------------------------------------
-struct PixelShader
-{
-	GLuint				gl_object;
-};
-
-//-----------------------------------------------------------------------------
-struct GPUProgram
-{
-	GLuint				gl_object;
-};
-
-/// OpenGLES2 renderer
-class GLESRenderer : public Renderer
-{
-public:
-
-						GLESRenderer();
-						~GLESRenderer();
-
-	void				init();
-	void				shutdown();
-
-	// Vertex buffers
-	VertexBufferId		create_vertex_buffer(size_t count, VertexFormat format, const void* vertices);
-	VertexBufferId		create_dynamic_vertex_buffer(size_t count, VertexFormat format, const void* vertices);
-	void				update_vertex_buffer(VertexBufferId id, size_t offset, size_t count, const void* vertices);
-	void				destroy_vertex_buffer(VertexBufferId id);
-
-	// Index buffers
-	IndexBufferId		create_index_buffer(size_t count, const void* indices);
-	void				destroy_index_buffer(IndexBufferId id);
-
-	// Textures
-	TextureId			create_texture(uint32_t width, uint32_t height, PixelFormat format, const void* data);
-	void				update_texture(TextureId id, uint32_t x, uint32_t y, uint32_t width, uint32_t height, const void* data);
-	void				destroy_texture(TextureId id);
-
-	void				bind_texture(uint32_t unit, TextureId texture);
-	void				set_texturing(uint32_t unit, bool texturing);
-	void				set_texture_wrap(uint32_t unit, TextureWrap wrap);
-	void				set_texture_filter(uint32_t unit, TextureFilter filter);
-
-	// Vertex shaders
-	VertexShaderId		create_vertex_shader(const char* program);
-	void				destroy_vertex_shader(VertexShaderId id);
-
-	// Pixel shaders
-	PixelShaderId 		create_pixel_shader(const char* program);
-	void				destroy_pixel_shader(PixelShaderId id);
-
-	// GPU programs
-	GPUProgramId		create_gpu_program(VertexShaderId vs, PixelShaderId ps);
-	void				destroy_gpu_program(GPUProgramId id);
-
-	void				set_gpu_program_bool_uniform(GPUProgramId id, const char* name, bool value);
-	void				set_gpu_program_int_uniform(GPUProgramId id, const char* name, int value);
-
-	void				set_gpu_program_vec2_uniform(GPUProgramId id, const char* name, const Vec2& value);
-	void				set_gpu_program_vec3_uniform(GPUProgramId id, const char* name, const Vec3& value);
-	void				set_gpu_program_vec4_uniform(GPUProgramId id, const char* name, const Vec4& value);
-
-	void				set_gpu_porgram_mat3_uniform(GPUProgramId id, const char* name, const Mat3& value);
-	void				set_gpu_program_mat4_uniform(GPUProgramId id, const char* name, const Mat4& value);
-
-	void				set_gpu_program_sampler_uniform(GPUProgramId id, const char* name, uint32_t value);
-
-	void				bind_gpu_program(GPUProgramId id) const;
-
-	// Frame buffers
-	// RenderBufferId	create_render_buffer(uint32_t width, uint32_t height, PixelFormat format);
-	// void				destroy_render_buffer(RenderBufferId id);
-
-	void				frame();
-
-	void				set_clear_color(const Color4& color);
-
-	// Lighting
-	void				set_ambient_light(const Color4& color);
-
-	void				set_backface_culling(bool culling);
-
-	// Fragment operations
-	void				set_depth_test(bool test);
-	void				set_depth_write(bool write);
-	void				set_depth_func(CompareFunction func);
-
-	void				set_blending(bool blending);
-	void				set_blending_params(BlendEquation equation, BlendFunction src, BlendFunction dst, const Color4& color);
-	void				set_color_write(bool write);
-
-	void				set_front_face(FrontFace face);
-
-	void				set_viewport_params(int32_t x, int32_t y, int32_t width, int32_t height);
-	void				get_viewport_params(int32_t& x, int32_t& y, int32_t& width, int32_t& height);
-
-	void				set_scissor(bool scissor);
-	void				set_scissor_params(int32_t x, int32_t y, int32_t width, int32_t height);
-	void				get_scissor_params(int32_t& x, int32_t& y, int32_t& width, int32_t& height);
-
-	Mat4				get_matrix(MatrixType type) const;
-	void				set_matrix(MatrixType type, const Mat4& matrix);
-
-	void				bind_vertex_buffer(VertexBufferId vb) const;
-	//void				bind_render_buffer(RenderBufferId id) const;
-
-	void				draw_triangles(IndexBufferId id) const;
-
-	void				draw_lines(const float* vertices, const float* colors, uint32_t count);
-
-private:
-
-	// Loads the default shaders
-	void				load_default_shaders();
-	void				unload_default_shaders();
-	void				reload_default_shaders();
-
-	// Activates a texture unit and returns true if succes
-	bool				activate_texture_unit(uint32_t unit);
-	bool				activate_light(uint32_t light);
-
-	// Shaders
-	GLint				find_gpu_program_uniform(GLuint program, const char* name) const;
-
-	// GL error checking
-	void				check_gl_errors() const;
-
-private:
-
-	HeapAllocator		m_allocator;
-
-	GLContext			m_context;
-
-	// Matrices
-	Mat4				m_matrix[MT_COUNT];
-
-	Mat4				m_model_view_matrix;
-	Mat4				m_model_view_projection_matrix;
-
-	// Limits
-	int32_t				m_max_texture_size;
-	int32_t				m_max_texture_units;
-	int32_t				m_max_vertex_indices;
-	int32_t				m_max_vertex_vertices;
-
-	float				m_max_anisotropy;
-	float				m_min_max_point_size[2];
-	float				m_min_max_line_width[2];
-
-	// Viewport and scissor
-	int32_t				m_viewport[4];
-	int32_t				m_scissor[4];
-
-	// Lighting
-	Color4				m_ambient_light_color;
-
-	// Texture management
-	IdTable 			m_textures_id_table;
-	Texture				m_textures[MAX_TEXTURES];
-
-	uint32_t			m_active_texture_unit;
-	GLuint				m_texture_unit[MAX_TEXTURE_UNITS];
-	GLenum				m_texture_unit_target[MAX_TEXTURE_UNITS];
-
-	// Vertex/Index buffer management
-	IdTable				m_vertex_buffers_id_table;
-	VertexBuffer		m_vertex_buffers[MAX_VERTEX_BUFFERS];
-
-	IdTable				m_index_buffers_id_table;
-	IndexBuffer			m_index_buffers[MAX_INDEX_BUFFERS];
-
-	// Vertex shader management
-	IdTable 			m_vertex_shaders_id_table;
-	VertexShader		m_vertex_shaders[MAX_VERTEX_SHADERS];
-
-	// Pixel shader management
-	IdTable 			m_pixel_shaders_id_table;
-	PixelShader			m_pixel_shaders[MAX_PIXEL_SHADERS];
-
-	// GPU program management
-	IdTable 			m_gpu_programs_id_table;
-	GPUProgram			m_gpu_programs[128];
-
-	// Render buffer management
-	//IdTable			m_render_buffers_id_table;
-	//GLRenderBuffer	m_render_buffers[MAX_RENDER_BUFFERS];
-
-	// Default shaders
-	VertexShaderId		m_default_vertex_shader;
-	PixelShaderId		m_default_pixel_shader;
-	GPUProgramId		m_default_gpu_program;
-};
-
-} // namespace crown

+ 0 - 105
engine/renderers/gles/GLESUtils.cpp

@@ -1,105 +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 "GLESUtils.h"
-
-namespace crown
-{
-
-//-----------------------------------------------------------------------------
-const GLenum GLES::COMPARE_FUNCTION_TABLE[CF_COUNT] =
-{
-	GL_NEVER,
-	GL_LESS,
-	GL_EQUAL,
-	GL_LEQUAL,
-	GL_GREATER,
-	GL_NOTEQUAL,
-	GL_GEQUAL,
-	GL_ALWAYS
-};
-
-//-----------------------------------------------------------------------------
-const GLenum GLES::BLEND_FUNCTION_TABLE[BF_COUNT] =
-{
-	GL_ZERO,
-	GL_ONE,
-	GL_SRC_COLOR,
-	GL_ONE_MINUS_SRC_COLOR,
-	GL_DST_COLOR,
-	GL_ONE_MINUS_DST_COLOR,
-	GL_SRC_ALPHA,
-	GL_ONE_MINUS_SRC_ALPHA,
-	GL_DST_ALPHA,
-	GL_ONE_MINUS_DST_ALPHA,
-	GL_ONE,						// BF_CONSTANT_COLOR not supported
-	GL_ONE,						// BF_ONE_MINUS_CONSTANT_COLOR not supported
-	GL_ONE,						// BF_CONSTANT_ALPHA not supported
-	GL_ONE,						// BF_ONE_MINUS_CONSTANT_ALPHA not supported
-	GL_SRC_ALPHA_SATURATE
-};
-
-//-----------------------------------------------------------------------------
-const GLenum GLES::BLEND_EQUATION_TABLE[BE_COUNT] =
-{
-	GL_FUNC_ADD,
-	GL_FUNC_SUBTRACT,
-	GL_FUNC_REVERSE_SUBTRACT,
-	GL_ONE,						// not supported
-	GL_ONE						// not supported
-};
-
-//-----------------------------------------------------------------------------
-const GLenum GLES::TEXTURE_WRAP_TABLE[TW_COUNT] =
-{
-	GL_REPEAT,
-	GL_REPEAT,
-	GL_CLAMP_TO_EDGE,
-	GL_REPEAT
-};
-
-//-----------------------------------------------------------------------------
-const GLenum GLES::TEXTURE_MIN_FILTER_TABLE[TF_COUNT] =
-{
-	GL_NEAREST,
-	GL_LINEAR,
-	GL_NEAREST_MIPMAP_LINEAR,
-	GL_LINEAR_MIPMAP_LINEAR,
-	GL_LINEAR_MIPMAP_LINEAR
-};
-
-//-----------------------------------------------------------------------------
-const GLenum GLES::TEXTURE_MAG_FILTER_TABLE[TF_COUNT] =
-{
-	GL_NEAREST,
-	GL_LINEAR,
-	GL_LINEAR,
-	GL_LINEAR,
-	GL_LINEAR
-};
-
-} // namespace crown
-

+ 0 - 143
engine/renderers/gles/GLESUtils.h

@@ -1,143 +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.
-*/
-
-#pragma once
-
-#include <GLES2/gl2.h>
-#include "Assert.h"
-#include "Texture.h"
-#include "Material.h"
-#include "PixelFormat.h"
-
-namespace crown
-{
-
-/// OpenGL utilities for converting from wrapped names to GL names and vice-versa.
-class GLES
-{
-public:
-
-	static GLenum			compare_function(CompareFunction function);
-	static GLenum			blend_function(BlendFunction function);
-	static GLenum			blend_equation(BlendEquation equation);
-	static GLenum			texture_wrap(TextureWrap wrap);
-	static void				texture_filter(TextureFilter filter, GLint& minFilter, GLint& magFilter);
-	static GLenum			pixel_format(PixelFormat format);
-	static PixelFormat		pixel_format_from_gl_format(GLenum format);
-
-private:
-
-	static const GLenum		COMPARE_FUNCTION_TABLE[CF_COUNT];
-	static const GLenum		BLEND_FUNCTION_TABLE[BF_COUNT];
-	static const GLenum		BLEND_EQUATION_TABLE[BE_COUNT];
-	static const GLenum		TEXTURE_WRAP_TABLE[TW_COUNT];
-	static const GLenum		TEXTURE_MIN_FILTER_TABLE[TF_COUNT];
-	static const GLenum		TEXTURE_MAG_FILTER_TABLE[TF_COUNT];
-
-	// Disable construction
-	GLES();
-};
-
-//-----------------------------------------------------------------------------
-inline GLenum GLES::compare_function(CompareFunction function)
-{
-	CE_ASSERT(function < CF_COUNT, "Compare function not supported");
-
-	return COMPARE_FUNCTION_TABLE[function];
-}
-
-//-----------------------------------------------------------------------------
-inline GLenum GLES::blend_function(BlendFunction function)
-{
-	CE_ASSERT(function < BF_COUNT, "Blend function not supported");
-
-	return BLEND_FUNCTION_TABLE[function];
-}
-
-//-----------------------------------------------------------------------------
-inline GLenum GLES::blend_equation(BlendEquation equation)
-{
-
-	CE_ASSERT(equation < BE_COUNT, "Blend equation not supported");
-
-	return BLEND_EQUATION_TABLE[equation];
-}
-
-//-----------------------------------------------------------------------------
-inline GLenum GLES::texture_wrap(TextureWrap wrap)
-{
-	CE_ASSERT(wrap < TW_COUNT, "Texture wrapper not supported");
-
-	return TEXTURE_WRAP_TABLE[wrap];
-}
-
-//-----------------------------------------------------------------------------
-inline void GLES::texture_filter(TextureFilter filter, GLint& minFilter, GLint& magFilter)
-{
-	CE_ASSERT(filter < TF_COUNT, "Texture filter not supported");
-
-	minFilter = TEXTURE_MIN_FILTER_TABLE[filter];
-	magFilter = TEXTURE_MAG_FILTER_TABLE[filter];
-}
-
-//-----------------------------------------------------------------------------
-inline GLenum GLES::pixel_format(PixelFormat format)
-{
-	switch (format)
-	{
-		case PF_RGBA_8:
-			return GL_RGBA;
-		case PF_RGB_8:
-			return GL_RGB;
-		case PF_LA_8:
-			return GL_LUMINANCE_ALPHA;
-		case PF_L_8:
-			return GL_LUMINANCE;
-		default:
-			return GL_RGB;
-	}
-}
-
-//-----------------------------------------------------------------------------
-inline PixelFormat GLES::pixel_format_from_gl_format(GLenum format)
-{
-	switch (format)
-	{
-		case GL_RGBA:
-			return PF_RGBA_8;
-		case GL_RGB:
-			return PF_RGB_8;
-		case GL_LUMINANCE_ALPHA:
-			return PF_LA_8;
-		case GL_LUMINANCE:
-			return PF_L_8;
-		default:
-			return PF_RGB_8;
-	}
-}
-
-} // namespace crown
-

+ 0 - 101
engine/renderers/gles/egl/GLContext.cpp

@@ -1,101 +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 <GLES2/gl2.h>
-
-#include "Assert.h"
-#include "GLContext.h"
-
-namespace crown
-{
-
-static ANativeWindow* awindow = NULL;
-
-//-----------------------------------------------------------------------------
-void set_android_window(ANativeWindow* window)
-{
-    CE_ASSERT_NOT_NULL(window);
-
-	awindow = window;
-}
-
-//-----------------------------------------------------------------------------
-GLContext::GLContext() :
-	num_configs(0)
-{
-}
-
-//-----------------------------------------------------------------------------
-void GLContext::create_context()
-{
-	EGLint format;
-
-	// 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 };
-
-    display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
-
-    eglInitialize(display, NULL, NULL);
-
-    eglBindAPI(EGL_OPENGL_ES_API);
-
-    eglChooseConfig(display, attrib_list, &config, 1, &num_configs);
-
-	eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &format);
-
-	ANativeWindow_setBuffersGeometry(awindow, 0, 0, format);
-
-    context = eglCreateContext(display, config, EGL_NO_CONTEXT, attributes);
-
-	surface = eglCreateWindowSurface(display, config, (EGLNativeWindowType)awindow, NULL);
-
-    eglMakeCurrent(display, surface, surface, context);
-}
-
-//-----------------------------------------------------------------------------
-void GLContext::destroy_context()
-{
- 	eglDestroyContext(display, context);
- 	eglDestroySurface(display, surface);
- 	eglTerminate(display);
-}
-
-//-----------------------------------------------------------------------------
-void GLContext::swap_buffers()
-{
-   	eglSwapBuffers(display, surface);
-}
-
-}

+ 1 - 0
engine/resource/FileBundle.cpp

@@ -33,6 +33,7 @@ OTHER DEALINGS IN THE SOFTWARE.
 #include "Resource.h"
 #include "StringUtils.h" 
 #include "Types.h"
+#include "OS.h"
 
 namespace crown
 {

+ 0 - 1
engine/resource/LuaResource.h

@@ -31,7 +31,6 @@ OTHER DEALINGS IN THE SOFTWARE.
 #include "Bundle.h"
 #include "Allocator.h"
 #include "File.h"
-#include "Log.h"
 
 namespace crown
 {

+ 0 - 56
engine/resource/MaterialResource.h

@@ -31,19 +31,12 @@ OTHER DEALINGS IN THE SOFTWARE.
 #include "Resource.h"
 #include "Vec3.h"
 #include "Color4.h"
-#include "Material.h"
-#include "Texture.h"
 #include "Bundle.h"
 #include "Allocator.h"
 
 namespace crown
 {
 
-/// Max texture layers supported by the material.
-/// @note The maximum number of usable layers depends on the graphic card/Renderer config.
-const uint32_t MAX_TEXTURE_LAYERS = 8;
-
-
 /// A material describes the visual properties of a surface.
 /// It is primarly intended for rendering purposes but can
 /// also be used to drive other types of systems such as sounds or physics.
@@ -75,55 +68,6 @@ public:
 	{
 		// TODO
 	}
-
-private:
-
-	Color4			m_ambient;
-	Color4			m_diffuse;
-	Color4			m_specular;
-	Color4			m_emission;
-	int32_t			m_shininess;
-
-	bool			m_lighting					: 1; // Lighting enabled
-	bool			m_texturing					: 1; // Texturing enabled
-	bool			m_backface_culling			: 1; // Backface-culling enabled
-	bool			m_separate_specular_color 	: 1; // Separate specular color enabled
-	bool			m_depth_test				: 1; // Depth test enabled
-	bool			m_depth_write				: 1; // Depth write enabled
-	bool			m_rescale_normals			: 1; // Auto normal rescaling enabled
-	bool			m_blending					: 1; // Blending enabled
-	bool			m_color_write				: 1; // Writing into color buffer enabled
-	bool			m_fog						: 1; // Fog enabled
-	bool			m_alpha_test				: 1; // Alpha test enabled
-	bool			m_point_sprite				: 1; // Point sprite enabled
-
-	ShadingType		m_shading_type;
-	PolygonMode		m_polygon_mode;
-	FrontFace		m_front_face;
-
-	CompareFunction	m_depth_func;
-
-	FogMode 		m_fog_mode;
-	float			m_fog_density;
-	float			m_fog_start;
-	float			m_fog_end;
-	Color4			m_fog_color;
-
-	CompareFunction	m_alpha_func;
-	float			m_alpha_ref;
-
-	float			m_point_size;
-	float			m_point_size_min;
-	float			m_point_size_max;
-
-	BlendEquation	m_blend_equation;
-	BlendFunction	m_blend_src;
-	BlendFunction	m_blend_dst;
-	Color4			m_blend_color;
-
-	// A material can contain up to MAX_TEXTURE_LAYERS texture layers.
-	// However, the maximum number of texture layers actually usable is Renderer-dependent.
-	ResourceId		m_textures[MAX_TEXTURE_LAYERS];
 };
 
 } // namespace crown

+ 67 - 25
engine/resource/MeshResource.h

@@ -29,9 +29,9 @@ OTHER DEALINGS IN THE SOFTWARE.
 #include "Types.h"
 #include "Resource.h"
 #include "PixelFormat.h"
-#include "Texture.h"
 #include "Allocator.h"
 #include "Bundle.h"
+#include "File.h"
 
 namespace crown
 {
@@ -41,10 +41,29 @@ const uint32_t MESH_VERSION = 1;
 
 struct MeshHeader
 {
-	uint32_t	version;
-	uint32_t	mesh_count;
-	uint32_t	joint_count;
-	uint32_t	padding[16];
+	uint32_t		version;
+	uint32_t		num_meshes;
+	uint32_t		num_joints;
+	uint32_t		padding[16];
+};
+
+struct VertexData
+{
+	uint32_t	    num_vertices;
+	VertexFormat	format;
+	uint32_t		offset;
+};
+
+struct IndexData
+{
+	uint32_t		num_indices;
+	uint32_t		offset;
+};
+
+struct MeshData
+{
+	VertexData		vertices;
+	IndexData		indices;
 };
 
 class MeshResource
@@ -56,22 +75,14 @@ public:
 	{
 		File* file = bundle.open(id);
 
-		MeshResource* resource = (MeshResource*)allocator.allocate(sizeof(MeshResource));
-		file->read(&resource->m_header, sizeof(MeshHeader));
-
-		// Read vertices
-		file->read(&resource->m_vertex_count, sizeof(uint32_t));
-		resource->m_vertices = (float*) allocator.allocate(sizeof(float) * resource->m_vertex_count);
-		file->read(resource->m_vertices, sizeof(float) * resource->m_vertex_count);
-
-		// Read triangles
-		file->read(&resource->m_index_count, sizeof(uint32_t));
-		resource->m_indices = (uint16_t*) allocator.allocate(sizeof(uint16_t) * resource->m_index_count);
-		file->read(resource->m_indices, sizeof(uint16_t) * resource->m_index_count);
+		const size_t file_size = file->size() - 12;
+		MeshResource* res = (MeshResource*) allocator.allocate(sizeof(MeshResource));
+		res->m_data = (uint8_t*) allocator.allocate(file_size);
+		file->read(res->m_data, file_size);
 
 		bundle.close(file);
 
-		return resource;
+		return res;
 	}
 
 	//-----------------------------------------------------------------------------
@@ -80,25 +91,56 @@ public:
 	}
 
 	//-----------------------------------------------------------------------------
-	static void unload(Allocator& , void* )
+	static void unload(Allocator& a, void* res)
 	{
+		MeshResource* resource = (MeshResource*)res;
+		a.deallocate(resource->m_data);
+		a.deallocate(resource);
 	}
 
 	//-----------------------------------------------------------------------------
 	static void offline(void* /*resource*/)
 	{
+	}
 
+	//-----------------------------------------------------------------------------
+	uint32_t num_vertices()
+	{
+		MeshData* data = (MeshData*) (m_data + sizeof(MeshHeader));
+		return data->vertices.num_vertices;
 	}
 
-public:
+	//-----------------------------------------------------------------------------
+	VertexFormat vertex_format()
+	{
+		MeshData* data = (MeshData*) (m_data + sizeof(MeshHeader));
+		return data->vertices.format;
+	}
 
-	MeshHeader			m_header;
+	//-----------------------------------------------------------------------------
+	float* vertices()
+	{
+		MeshData* data = (MeshData*) (m_data + sizeof(MeshHeader));
+		return (float*) (m_data + data->vertices.offset);
+	}
 
-	size_t				m_vertex_count;
-	float*				m_vertices;
+	//-----------------------------------------------------------------------------
+	uint32_t num_indices()
+	{
+		MeshData* data = (MeshData*) (m_data + sizeof(MeshHeader));
+		return data->indices.num_indices;
+	}
+
+	//-----------------------------------------------------------------------------
+	uint16_t* indices()
+	{
+		MeshData* data = (MeshData*) (m_data + sizeof(MeshHeader));
+		return (uint16_t*) (m_data + data->indices.offset);
+	}
+
+public:
 
-	size_t				m_index_count;
-	uint16_t*			m_indices;
+	uint8_t* m_data;
 };
 
 } // namespace crown

Някои файлове не бяха показани, защото твърде много файлове са промени