Преглед изворни кода

Merge branch 'master' into audio

Conflicts:
	engine/Android.mk
	engine/Device.cpp
mikymod пре 12 година
родитељ
комит
79973e5200
71 измењених фајлова са 3370 додато и 3943 уклоњено
  1. 5 11
      engine/Android.mk
  2. 10 12
      engine/CMakeLists.txt
  3. 12 0
      engine/Config.h.in
  4. 2 5
      engine/Crown.h
  5. 72 24
      engine/Device.cpp
  6. 13 7
      engine/Device.h
  7. 2 2
      engine/FPSSystem.cpp
  8. 2 2
      engine/audio/SoundRenderer.h
  9. 1 3
      engine/audio/al/ALRenderer.cpp
  10. 5 1
      engine/compilers/BundleCompiler.cpp
  11. 2 0
      engine/compilers/BundleCompiler.h
  12. 34 29
      engine/compilers/mesh/MeshCompiler.cpp
  13. 6 40
      engine/compilers/mesh/MeshCompiler.h
  14. 0 0
      engine/compilers/mesh/tinyxml2.cpp
  15. 0 0
      engine/compilers/mesh/tinyxml2.h
  16. 26 42
      engine/core/containers/IdTable.h
  17. 0 38
      engine/core/mem/Allocator.cpp
  18. 15 5
      engine/core/mem/LinearAllocator.cpp
  19. 2 0
      engine/core/mem/LinearAllocator.h
  20. 43 16
      engine/core/mem/Memory.cpp
  21. 10 0
      engine/core/mem/Memory.h
  22. 1 1
      engine/lua/LuaStack.h
  23. 38 0
      engine/lua/LuaWindow.cpp
  24. 12 0
      engine/os/android/AndroidDevice.cpp
  25. 13 1
      engine/os/android/Config.h
  26. 21 0
      engine/os/android/OsWindow.cpp
  27. 12 0
      engine/os/android/OsWindow.h
  28. 12 0
      engine/os/android/java/CrownActivity.java
  29. 5 0
      engine/os/android/java/CrownLib.java
  30. 3 0
      engine/os/linux/LinuxOS.cpp
  31. 34 0
      engine/os/linux/OsWindow.cpp
  32. 7 0
      engine/os/linux/OsWindow.h
  33. 5 40
      engine/os/linux/main.cpp
  34. 295 0
      engine/os/linux/main2.cpp
  35. 4 11
      engine/os/posix/Thread.h
  36. 98 0
      engine/renderers/CommandBuffer.h
  37. 114 0
      engine/renderers/ConstantBuffer.h
  38. 1 1
      engine/renderers/DebugRenderer.cpp
  39. 0 38
      engine/renderers/IndexBuffer.h
  40. 0 105
      engine/renderers/Material.h
  41. 0 117
      engine/renderers/PixelFormat.cpp
  42. 80 70
      engine/renderers/PixelFormat.h
  43. 0 33
      engine/renderers/PixelShader.h
  44. 0 37
      engine/renderers/RenderBuffer.h
  45. 327 0
      engine/renderers/RenderContext.h
  46. 645 168
      engine/renderers/Renderer.h
  47. 209 0
      engine/renderers/RendererTypes.h
  48. 0 68
      engine/renderers/Texture.h
  49. 0 46
      engine/renderers/VertexBuffer.h
  50. 0 67
      engine/renderers/VertexFormat.cpp
  51. 79 10
      engine/renderers/VertexFormat.h
  52. 0 33
      engine/renderers/VertexShader.h
  53. 412 843
      engine/renderers/gl/GLRenderer.cpp
  54. 475 199
      engine/renderers/gl/GLRenderer.h
  55. 0 113
      engine/renderers/gl/GLUtils.cpp
  56. 0 139
      engine/renderers/gl/GLUtils.h
  57. 1 0
      engine/renderers/gl/egl/GLContext.cpp
  58. 5 0
      engine/renderers/gl/egl/GLContext.h
  59. 3 1
      engine/renderers/gl/glx/GLContext.cpp
  60. 6 1
      engine/renderers/gl/glx/GLContext.h
  61. 0 971
      engine/renderers/gles/GLESRenderer.cpp
  62. 0 276
      engine/renderers/gles/GLESRenderer.h
  63. 0 105
      engine/renderers/gles/GLESUtils.cpp
  64. 0 143
      engine/renderers/gles/GLESUtils.h
  65. 0 56
      engine/resource/MaterialResource.h
  66. 33 2
      engine/resource/MeshResource.h
  67. 1 1
      engine/resource/Resource.h
  68. 18 9
      engine/resource/ResourceLoader.cpp
  69. 4 0
      engine/resource/ResourceLoader.h
  70. 0 1
      engine/resource/TextureResource.h
  71. 135 0
      utils/code-cleaner.rb

+ 5 - 11
engine/Android.mk

@@ -54,7 +54,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\
@@ -87,12 +86,9 @@ LOCAL_SRC_FILES :=\
 	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\
@@ -148,13 +144,11 @@ 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/sles\
+	$(LOCAL_PATH)/renderers/gl\
+	$(LOCAL_PATH)/renderers/gl/egl\
 	$(LOCAL_PATH)/third/ARMv7/luajit/include/luajit-2.0\
 	$(LOCAL_PATH)/third/ARMv7/oggvorbis/include\
-	$(LOCAL_PATH)/
-
+	
 LOCAL_CPPFLAGS	:= -g -fexceptions -std=c++03 -ansi -pedantic -Wall -Wextra -Wno-long-long -Wno-variadic-macros
 LOCAL_LDLIBS	:= -llog -landroid -lEGL -lGLESv2 -lz -lOpenSLES
 LOCAL_SHARED_LIBRARIES := luajit-5.1

+ 10 - 12
engine/CMakeLists.txt

@@ -193,7 +193,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
@@ -259,16 +258,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
@@ -350,6 +344,8 @@ set (AUDIO_HEADERS
 set (COMPILER_SRC
 	compilers/Compiler.cpp
 	compilers/BundleCompiler.cpp
+	compilers/mesh/MeshCompiler.cpp
+	compilers/mesh/tinyxml2.cpp
 	compilers/lua/LuaCompiler.cpp
 	compilers/texture/TextureCompiler.cpp
 	compilers/sound/SoundCompiler.cpp
@@ -359,6 +355,8 @@ set (COMPILER_SRC
 set (COMPILER_HEADER
 	compilers/Compiler.h
 	compilers/BundleCompiler.h
+	compilers/mesh/MeshCompiler.h
+	compilers/mesh/tinyxml2.h
 	compilers/lua/LuaCompiler.h
 	compilers/texture/TextureCompiler.h
 	compilers/sound/SoundCompiler.h
@@ -396,13 +394,11 @@ if (LINUX)
 
 	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
 	)
 
@@ -488,13 +484,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
 	)
 
@@ -569,12 +563,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

+ 2 - 5
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"
@@ -146,4 +143,4 @@ OTHER DEALINGS IN THE SOFTWARE.
 
 // Engine/Audio
 #include "SoundRenderer.h"
-#include "OggDecoder.h"
+#include "OggDecoder.h"

+ 72 - 24
engine/Device.cpp

@@ -69,12 +69,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),
@@ -95,15 +97,16 @@ Device::Device() :
 	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),
 	m_lua_environment(NULL),
 	m_renderer(NULL),
 	m_debug_renderer(NULL),
-
 	m_sound_renderer(NULL),
 
+	m_bundle_compiler(NULL),
 	m_resource_manager(NULL),
 	m_resource_bundle(NULL),
 
@@ -195,7 +198,7 @@ void Device::init()
 	Log::d("Input manager created.");
 
 	// default_allocator, maybe it needs fix
-	m_window = CE_NEW(default_allocator(), OsWindow)(m_preferred_window_width, m_preferred_window_height, m_parent_window_handle);
+	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");
 
@@ -204,7 +207,7 @@ void Device::init()
 	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.");
@@ -218,17 +221,17 @@ void Device::init()
 	Log::d("Lua environment created.");
 
 	// FIXME: replace default_allocator with linear m_allocator
-	m_sound_renderer = CE_NEW(default_allocator(), SoundRenderer)(m_allocator);
+	m_sound_renderer = CE_NEW(m_allocator, SoundRenderer)(m_allocator);
 	m_sound_renderer->init();
 	Log::d("SoundRenderer created.");
 
-	ResourceId rid = m_resource_manager->load("sound", "sounds/birds1");
-	m_resource_manager->flush();
+	// ResourceId rid = m_resource_manager->load("sound", "sounds/birds1");
+	// m_resource_manager->flush();
 
-	SoundResource* res = (SoundResource*)m_resource_manager->data(rid);
+	// SoundResource* res = (SoundResource*)m_resource_manager->data(rid);
 
-	WaveSample sample;
-	sample.create(res->data(), res->size(), res->sample_rate(), res->channels(), res->block_size(), res->bits_ps());
+	// WaveSample sample;
+	// sample.create(res->data(), res->size(), res->sample_rate(), res->channels(), res->block_size(), res->bits_ps());
 
 
 	// OggDecoder decoder((char*)stream->data(), stream->size());
@@ -269,6 +272,9 @@ void Device::init()
 	m_is_init = true;
 	start();
 
+	// Show main window
+	m_window->show();
+
 	// Execute lua boot file
 	if (m_lua_environment->load_and_execute(m_boot_file))
 	{
@@ -282,8 +288,7 @@ void Device::init()
 		pause();
 	}
 
-	// Show main window
-	m_window->show();
+	Log::d("Total allocated size: %llu", m_allocator.allocated_size());
 
 	if (m_quit_after_init == 1)
 	{
@@ -315,7 +320,7 @@ void Device::shutdown()
 		m_sound_renderer->shutdown();
 
 		// FIXME: replace default_allocator with linear m_allocator
-		CE_DELETE(default_allocator(), m_sound_renderer);
+		CE_DELETE(m_allocator, m_sound_renderer);
 	}
 
 	Log::i("Releasing LuaEnvironment...");
@@ -342,14 +347,13 @@ 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...");
 	if (m_window)
 	{
-		CE_DELETE(default_allocator(), m_window);
+		CE_DELETE(m_allocator, m_window);
 	}
 
 	Log::i("Releasing ResourceManager...");
@@ -525,11 +529,18 @@ 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;
 
 	if (!m_is_paused)
 	{
@@ -543,7 +554,7 @@ void Device::frame()
 			pause();
 		}
 
-		m_debug_renderer->draw_all();
+		callback(m_last_delta_time);
 		m_renderer->frame();
 	}
 
@@ -561,7 +572,7 @@ ResourcePackage* Device::create_resource_package(const char* name)
 	m_resource_manager->flush();
 
 	PackageResource* package_res = (PackageResource*) m_resource_manager->data(package_id);
-	ResourcePackage* package = CE_NEW(m_allocator, ResourcePackage)(*m_resource_manager, package_id, package_res);
+	ResourcePackage* package = CE_NEW(default_allocator(), ResourcePackage)(*m_resource_manager, package_id, package_res);
 
 	return package;
 }
@@ -572,7 +583,7 @@ void Device::destroy_resource_package(ResourcePackage* package)
 	CE_ASSERT_NOT_NULL(package);
 
 	m_resource_manager->unload(package->resource_id());
-	CE_DELETE(m_allocator, package);
+	CE_DELETE(default_allocator(), package);
 }
 
 //-----------------------------------------------------------------------------
@@ -660,9 +671,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);
 	}
 
@@ -745,10 +771,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;
+}
+
+void nothing(float)
+{
+	device()->renderer()->set_layer_clear(0, CLEAR_COLOR | CLEAR_DEPTH, Color4::LIGHTBLUE, 1.0f);
+	device()->renderer()->commit(0);
 }
 
-} // namespace crown
+} // namespace crown

+ 13 - 7
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
 {
 
@@ -54,6 +52,9 @@ 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
 /// the engine subsystems and related stuff.
@@ -85,10 +86,12 @@ public:
 	/// 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();
 
@@ -103,7 +106,8 @@ public:
 	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);
@@ -147,7 +151,6 @@ private:
 private:
 
 	// Used to allocate all subsystems
-	uint8_t					m_subsystems_heap[MAX_SUBSYSTEMS_HEAP];
 	LinearAllocator			m_allocator;
 
 	// Preferred settings
@@ -174,6 +177,7 @@ private:
 	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;
@@ -205,6 +209,8 @@ private:
 	friend class MainThread;
 };
 
+CE_EXPORT void init();
+CE_EXPORT void shutdown();
 CE_EXPORT Device* device();
 
-} // namespace crown
+} // 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());
 }
 
 //-----------------------------------------------------------------------	

+ 2 - 2
engine/audio/SoundRenderer.h

@@ -162,8 +162,8 @@ private:
 
 	SoundRendererBackend*	m_backend;
 
-	IdTable 				m_buffers_id_table;
-	IdTable 				m_sources_id_table;
+	IdTable<MAX_SOUND_BUFFERS>		m_buffers_id_table;
+	IdTable<MAX_SOUND_SOURCES>		m_sources_id_table;
 
 	uint32_t				m_num_buffers;
 	uint32_t				m_num_sources;

+ 1 - 3
engine/audio/al/ALRenderer.cpp

@@ -114,9 +114,7 @@ private:
 
 //-----------------------------------------------------------------------------
 SoundRenderer::SoundRenderer(Allocator& allocator) : 
-	m_allocator(allocator), 
-	m_buffers_id_table(default_allocator(), MAX_SOUND_BUFFERS),
-	m_sources_id_table(default_allocator(), MAX_SOUND_SOURCES),
+	m_allocator(allocator),
 	m_num_buffers(0),
 	m_num_sources(0)
 {

+ 5 - 1
engine/compilers/BundleCompiler.cpp

@@ -98,7 +98,11 @@ bool BundleCompiler::compile(const char* bundle_dir, const char* source_dir)
 		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);
 		}

+ 2 - 0
engine/compilers/BundleCompiler.h

@@ -26,6 +26,7 @@ OTHER DEALINGS IN THE SOFTWARE.
 
 #pragma once
 
+#include "MeshCompiler.h"
 #include "TextureCompiler.h"
 #include "LuaCompiler.h"
 #include "SoundCompiler.h"
@@ -51,6 +52,7 @@ private:
 
 private:
 
+	MeshCompiler	m_mesh;
 	TextureCompiler	m_texture;
 	LuaCompiler 	m_lua;
 	SoundCompiler	m_sound;

+ 34 - 29
engine/compilers/dae/DAECompiler.cpp → engine/compilers/mesh/MeshCompiler.cpp

@@ -26,7 +26,11 @@ OTHER DEALINGS IN THE SOFTWARE.
 
 #include <iostream>
 #include <sstream>
-#include "DAECompiler.h"
+#include <fstream>
+#include "MeshCompiler.h"
+#include "DynamicString.h"
+#include "TempAllocator.h"
+#include "Filesystem.h"
 
 using tinyxml2::XMLDocument;
 using tinyxml2::XMLElement;
@@ -40,23 +44,24 @@ namespace crown
 {
 
 //-----------------------------------------------------------------------------
-DAECompiler::DAECompiler()
+MeshCompiler::MeshCompiler()
 {
-
 }
 
 //-----------------------------------------------------------------------------
-DAECompiler::~DAECompiler()
+MeshCompiler::~MeshCompiler()
 {
-
 }
 
 //-----------------------------------------------------------------------------
-size_t DAECompiler::compile_impl(const char* resource_path)
+size_t MeshCompiler::compile_impl(Filesystem& fs, const char* resource_path)
 {
 	DAEModel model;
 
-	if (!parse_collada(resource_path, model))
+	TempAllocator256 temp;
+	DynamicString path(temp);
+	fs.get_absolute_path(resource_path, path);
+	if (!parse_collada(path.c_str(), model))
 	{
 		return 0;
 	}
@@ -104,21 +109,21 @@ size_t DAECompiler::compile_impl(const char* resource_path)
 }
 
 //-----------------------------------------------------------------------------
-void DAECompiler::write_impl(std::fstream& out_file)
+void MeshCompiler::write_impl(File* out_file)
 {
-	out_file.write((char*) &m_mesh_header, sizeof(MeshHeader));
+	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));
+	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));
+	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)
+bool MeshCompiler::parse_collada(const char* path, DAEModel& m)
 {
 	XMLDocument doc;
 
@@ -168,7 +173,7 @@ bool DAECompiler::parse_collada(const char* path, DAEModel& m)
 }
 
 //-----------------------------------------------------------------------------
-bool DAECompiler::parse_geometry(XMLElement* geometry, DAEGeometry& g)
+bool MeshCompiler::parse_geometry(XMLElement* geometry, DAEGeometry& g)
 {
 	// Read geometry id
 	const char* geom_id = geometry->Attribute("id");
@@ -203,7 +208,7 @@ bool DAECompiler::parse_geometry(XMLElement* geometry, DAEGeometry& g)
 }
 
 //-----------------------------------------------------------------------------
-bool DAECompiler::parse_mesh(XMLElement* mesh, DAEMesh& m)
+bool MeshCompiler::parse_mesh(XMLElement* mesh, DAEMesh& m)
 {
 	/// Read sources
 	XMLElement* source = mesh->FirstChildElement("source");
@@ -251,7 +256,7 @@ bool DAECompiler::parse_mesh(XMLElement* mesh, DAEMesh& m)
 }
 
 //-----------------------------------------------------------------------------
-bool DAECompiler::parse_source(XMLElement* source, DAESource& s)
+bool MeshCompiler::parse_source(XMLElement* source, DAESource& s)
 {
 	// Read source id
 	const char* source_id = source->Attribute("id");
@@ -293,7 +298,7 @@ bool DAECompiler::parse_source(XMLElement* source, DAESource& s)
 }
 
 //-----------------------------------------------------------------------------
-bool DAECompiler::parse_float_array(XMLElement* array, DAEFloatArray& a)
+bool MeshCompiler::parse_float_array(XMLElement* array, DAEFloatArray& a)
 {
 	// Read float array id
 	const char* float_array_id = array->Attribute("id");
@@ -325,7 +330,7 @@ bool DAECompiler::parse_float_array(XMLElement* array, DAEFloatArray& a)
 }
 
 //-----------------------------------------------------------------------------
-bool DAECompiler::parse_technique_common(XMLElement* technique, DAETechniqueCommon& t)
+bool MeshCompiler::parse_technique_common(XMLElement* technique, DAETechniqueCommon& t)
 {
 	// Read accessor
 	XMLElement* accessor = technique->FirstChildElement("accessor");
@@ -339,7 +344,7 @@ bool DAECompiler::parse_technique_common(XMLElement* technique, DAETechniqueComm
 }
 
 //-----------------------------------------------------------------------------
-bool DAECompiler::parse_accessor(XMLElement* accessor, DAEAccessor& a)
+bool MeshCompiler::parse_accessor(XMLElement* accessor, DAEAccessor& a)
 {
 	// Read accessor source
 	const char* accessor_source = accessor->Attribute("source");
@@ -391,7 +396,7 @@ bool DAECompiler::parse_accessor(XMLElement* accessor, DAEAccessor& a)
 }
 
 //-----------------------------------------------------------------------------
-bool DAECompiler::parse_param(XMLElement* param, DAEParam& p)
+bool MeshCompiler::parse_param(XMLElement* param, DAEParam& p)
 {
 	// Read param name
 	const char* param_name = param->Attribute("name");
@@ -417,7 +422,7 @@ bool DAECompiler::parse_param(XMLElement* param, DAEParam& p)
 }
 
 //-----------------------------------------------------------------------------
-bool DAECompiler::parse_vertices(XMLElement* vertices, DAEVertices& v)
+bool MeshCompiler::parse_vertices(XMLElement* vertices, DAEVertices& v)
 {
 	// Read vertices id
 	const char* vertices_id = vertices->Attribute("id");
@@ -454,7 +459,7 @@ bool DAECompiler::parse_vertices(XMLElement* vertices, DAEVertices& v)
 }
 
 //-----------------------------------------------------------------------------
-bool DAECompiler::parse_input(XMLElement* input, DAEInput& i)
+bool MeshCompiler::parse_input(XMLElement* input, DAEInput& i)
 {
 	// Read input semantic
 	const char* input_semantic = input->Attribute("semantic");
@@ -486,7 +491,7 @@ bool DAECompiler::parse_input(XMLElement* input, DAEInput& i)
 }
 
 //-----------------------------------------------------------------------------
-bool DAECompiler::parse_polylist(XMLElement* polylist, DAEPolylist& p)
+bool MeshCompiler::parse_polylist(XMLElement* polylist, DAEPolylist& p)
 {
 	// Read polylist count
 	if (polylist->QueryUnsignedAttribute("count", &p.count) != XML_NO_ERROR)
@@ -550,7 +555,7 @@ bool DAECompiler::parse_polylist(XMLElement* polylist, DAEPolylist& p)
 }
 
 //-----------------------------------------------------------------------------
-bool DAECompiler::find_vertices(const DAEMesh& mesh, DAESource& source_out)
+bool MeshCompiler::find_vertices(const DAEMesh& mesh, DAESource& source_out)
 {
 	const vector<DAESource>& sources = mesh.sources;
 	const vector<DAEInput>& inputs = mesh.vertices.inputs;
@@ -576,7 +581,7 @@ bool DAECompiler::find_vertices(const DAEMesh& mesh, DAESource& source_out)
 }
 
 //-----------------------------------------------------------------------------
-bool DAECompiler::find_normals(const DAEMesh& mesh, DAESource& source_out)
+bool MeshCompiler::find_normals(const DAEMesh& mesh, DAESource& source_out)
 {
 	const vector<DAESource>& sources = mesh.sources;
 	const vector<DAEInput>& inputs = mesh.polylist.inputs;
@@ -603,7 +608,7 @@ bool DAECompiler::find_normals(const DAEMesh& mesh, DAESource& source_out)
 }
 
 //-----------------------------------------------------------------------------
-bool DAECompiler::extract_vertex_indices(const DAEMesh& mesh, vector<uint16_t>& indices_out)
+bool MeshCompiler::extract_vertex_indices(const DAEMesh& mesh, vector<uint16_t>& indices_out)
 {
 	// Find vertices
 	DAESource vertex_source;
@@ -614,10 +619,10 @@ bool DAECompiler::extract_vertex_indices(const DAEMesh& mesh, vector<uint16_t>&
 
 	// Read vertices
 	const vector<uint32_t>& primitives = mesh.polylist.p;
-	const vector<float>& vertices = vertex_source.float_array.array;
+	//const vector<float>& vertices = vertex_source.float_array.array;
 
 	// FIXME FIXME FIXME
-	uint32_t offset = 0;
+	//uint32_t offset = 0;
 	uint32_t attribs = mesh.polylist.inputs.size();
 
 	uint32_t prims = 0;

+ 6 - 40
engine/compilers/dae/DAECompiler.h → engine/compilers/mesh/MeshCompiler.h

@@ -31,7 +31,7 @@ OTHER DEALINGS IN THE SOFTWARE.
 #include <vector>
 
 #include "Compiler.h"
-#include "MeshFormat.h"
+#include "MeshResource.h"
 #include "tinyxml2.h"
 
 using tinyxml2::XMLElement;
@@ -40,40 +40,6 @@ 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
 {
@@ -157,15 +123,15 @@ struct DAEModel
 	std::vector<DAEGeometry>	geometries;
 };
 
-class DAECompiler : public Compiler
+class MeshCompiler : public Compiler
 {
 public:
 
-						DAECompiler();
-						~DAECompiler();
+						MeshCompiler();
+						~MeshCompiler();
 
-	size_t				compile_impl(const char* resource_path);
-	void				write_impl(std::fstream& out_file);
+	size_t				compile_impl(Filesystem& fs, const char* resource_path);
+	void				write_impl(File* out_file);
 
 private:
 

+ 0 - 0
engine/compilers/dae/tinyxml2.cpp → engine/compilers/mesh/tinyxml2.cpp


+ 0 - 0
engine/compilers/dae/tinyxml2.h → engine/compilers/mesh/tinyxml2.h


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

+ 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 - 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);
 	}
 
 	//-----------------------------------------------------------------------------

+ 38 - 0
engine/lua/LuaWindow.cpp

@@ -108,6 +108,40 @@ CE_EXPORT int window_move(lua_State* L)
 	return 0;
 }
 
+//-----------------------------------------------------------------------------
+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()->set_resizable(stack.get_bool(1));
+
+	return 0;
+}
+
 //-----------------------------------------------------------------------------
 CE_EXPORT int window_show_cursor(lua_State* L)
 {
@@ -189,6 +223,10 @@ 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);

+ 12 - 0
engine/os/android/AndroidDevice.cpp

@@ -32,6 +32,18 @@ OTHER DEALINGS IN THE SOFTWARE.
 namespace crown
 {
 
+//-----------------------------------------------------------------------------
+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*/)
 {

+ 13 - 1
engine/os/android/Config.h

@@ -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

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

@@ -85,6 +85,27 @@ void OsWindow::move(uint32_t /*x*/, uint32_t /*y*/)
 {
 }
 
+//-----------------------------------------------------------------------------
+void OsWindow::minimize()
+{
+}
+
+//-----------------------------------------------------------------------------
+void OsWindow::restore()
+{
+}
+
+//-----------------------------------------------------------------------------
+bool OsWindow::is_resizable() const
+{
+	return false;
+}
+
+//-----------------------------------------------------------------------------
+void OsWindow::set_resizable(bool /*resizeable*/)
+{
+}
+
 //-----------------------------------------------------------------------------
 void OsWindow::show_cursor()
 {

+ 12 - 0
engine/os/android/OsWindow.h

@@ -59,6 +59,18 @@ 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			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			show_cursor();
 

+ 12 - 0
engine/os/android/java/CrownActivity.java

@@ -68,6 +68,9 @@ public class CrownActivity extends Activity
     {
         super.onCreate(savedInstanceState);
 
+        // Initializes low-level systems (memory, os etc.)
+        CrownLib.initCrown();
+
 		// init AssetManager
 		mAssetManager = getAssets();
 		CrownLib.initAssetManager(mAssetManager);
@@ -105,6 +108,15 @@ public class CrownActivity extends Activity
 		Log.i(TAG, "Crown Activity paused");
 	}
 
+//-----------------------------------------------------------------------------
+	public void onDestroy()
+	{
+		super.onDestroy();
+
+		CrownLib.shutdownDevice();
+		CrownLib.shutdownCrown();
+	}
+
 //-----------------------------------------------------------------------------
 	public boolean onTouchEvent(MotionEvent event)
 	{

+ 5 - 0
engine/os/android/java/CrownLib.java

@@ -36,9 +36,14 @@ 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 		initDevice();
+	public static native void		shutdownDevice();
 	public static native void		pauseDevice();
 	public static native void		unpauseDevice();
 	public static native void		stopDevice();

+ 3 - 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>
@@ -273,6 +274,8 @@ const char* get_env(const char* env)
 //-----------------------------------------------------------------------------
 void init_os()
 {
+	XInitThreads();
+
 	// Initilize the base time
 	clock_gettime(CLOCK_MONOTONIC, &base_time);
 }

+ 34 - 0
engine/os/linux/OsWindow.cpp

@@ -100,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,6 +215,39 @@ void OsWindow::move(uint32_t x, uint32_t y)
 	XMoveWindow(m_x11_display, m_x11_window, x, y);
 }
 
+//-----------------------------------------------------------------------------
+void OsWindow::minimize()
+{
+	XIconifyWindow(m_x11_display, m_x11_window, DefaultScreen(m_x11_display));
+}
+
+//-----------------------------------------------------------------------------
+void OsWindow::restore()
+{
+	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()
 {

+ 7 - 0
engine/os/linux/OsWindow.h

@@ -54,6 +54,12 @@ public:
 	void			resize(uint32_t width, uint32_t height);
 	void			move(uint32_t x, uint32_t y);
 
+	void			minimize();
+	void			restore();
+
+	bool			is_resizable() const;
+	void			set_resizable(bool resizable);
+
 	void			show_cursor();
 	void			hide_cursor();
 
@@ -75,6 +81,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;

+ 5 - 40
engine/os/linux/main.cpp

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

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

@@ -0,0 +1,295 @@
+/*
+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 ib;
+VertexBufferId 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;"
+	"	gl_FrontColor = vec4(vec3(1, 0, 0), 1.0);"
+	"}";
+
+static const char* default_fragment = 
+	"void main(void)"
+	"{"
+	"	gl_FragColor = vec4(1.0, 0.0, 0.0, 1.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) * texture(u_lightmap_0, tex_coord0) * color * u_brightness;"
+	"}";
+
+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;
+	}
+
+	// //-----------------------
+	// r->set_state(prim | STATE_DEPTH_WRITE | STATE_COLOR_WRITE | STATE_CULL_CCW);
+	// r->set_vertex_buffer(vb);
+	// r->set_index_buffer(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_CCW);
+	// r->set_vertex_buffer(vb);
+	// r->set_index_buffer(ib);
+	// r->set_program(default_program);
+
+	// 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_CCW);
+	// r->set_vertex_buffer(vb);
+	// r->set_index_buffer(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);
+
+	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;
+	}
+	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);
+
+	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_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 mesh
+	ResourceManager* resman = engine->resource_manager();
+	// ResourceId mesh = resman->load("mesh", "monkey");
+	ResourceId texture = resman->load("texture", "grass");
+	ResourceId lightmap = resman->load("texture", "lightmap");
+	resman->flush();
+
+	//MeshResource* mesh_resource = (MeshResource*)resman->data(mesh);
+	TextureResource* texture_resource = (TextureResource*)resman->data(texture);
+	TextureResource* lightmap_resource = (TextureResource*)resman->data(lightmap);
+
+	// Create vb/ib
+	r = engine->renderer();
+	//vb = r->create_vertex_buffer(mesh_resource->m_vertex_count / 3, VERTEX_P3, mesh_resource->m_vertices);
+	//ib = r->create_index_buffer(mesh_resource->m_index_count, mesh_resource->m_indices);
+	(void)vb;
+	(void)ib;
+
+	// 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);
+	r->destroy_index_buffer(ib);
+	r->destroy_vertex_buffer(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();
+}

+ 4 - 11
engine/os/posix/Thread.h

@@ -126,12 +126,10 @@ inline void Thread::stop()
 {
 	CE_ASSERT(m_is_running, "Thread is not running");
 	
-	m_is_running = false;
-
 	int32_t result = pthread_join(m_handle, NULL);
-
 	CE_ASSERT(result == 0, "Thread join failed. errno: %d", result);
 
+	m_is_running = false;
 	m_handle = 0;
 }
 
@@ -152,15 +150,10 @@ inline int32_t Thread::run()
 //-----------------------------------------------------------------------------
 inline void* Thread::thread_proc(void* arg)
 {
-	Thread* thread = (Thread*)arg;
-
-	int32_t result = thread->run();
-
-	CE_ASSERT(result == 0, "Function failed");
-
-	thread->m_is_running = false;
+	static int32_t result = -1;
+	result = ((Thread*)arg)->run();
 
-	return NULL;
+	return (void*)&result;
 }
 
 

+ 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 - 38
engine/renderers/IndexBuffer.h

@@ -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.
-*/
-
-#pragma once
-
-#include "Types.h"
-
-namespace crown
-{
-
-// Max number of index buffers a renderer can hold.
-const uint32_t MAX_INDEX_BUFFERS = 4096;
-
-} // namespace crown
-

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

+ 80 - 70
engine/renderers/PixelFormat.h

@@ -27,87 +27,97 @@ 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 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;
+			}
+		}
+	}
 
 	/// 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

+ 0 - 37
engine/renderers/RenderBuffer.h

@@ -1,37 +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 "Types.h"
-
-namespace crown
-{
-
-// Max number of textures a renderer can hold.
-const uint32_t MAX_RENDER_BUFFERS = 32;
-
-} // 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

+ 209 - 0
engine/renderers/RendererTypes.h

@@ -0,0 +1,209 @@
+/*
+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
+{
+	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
+};
+
+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

+ 0 - 68
engine/renderers/Texture.h

@@ -1,68 +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 "Types.h"
-
-namespace crown
-{
-
-// Max number of textures a renderer can hold.
-const uint32_t MAX_TEXTURES = 4096;
-
-enum TextureMode
-{
-	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
-};
-
-/// Enumerates the hardware filter to use when applying a texture
-enum TextureFilter
-{
-	TF_NEAREST		= 0,
-	TF_LINEAR		= 1,
-	TF_BILINEAR		= 2,
-	TF_TRILINEAR	= 3,
-	TF_ANISOTROPIC	= 4,
-	TF_COUNT
-};
-
-/// Enumerates the wrapping mode to use when applying a texture
-enum TextureWrap
-{
-	TW_REPEAT			= 0,
-	TW_CLAMP			= 1,
-	TW_CLAMP_TO_EDGE	= 2,
-	TW_CLAMP_TO_BORDER	= 3,
-	TW_COUNT
-};
-
-} // namespace crown

+ 0 - 46
engine/renderers/VertexBuffer.h

@@ -1,46 +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 "Types.h"
-
-namespace crown
-{
-
-// Max number of vertex buffers a renderer can hold.
-const uint32_t MAX_VERTEX_BUFFERS = 4096;
-
-enum VertexBufferMode
-{
-	VBM_VERTEX_ONLY		= 0,
-	VBM_TEXTURE_COORDS	= 1,
-	VBM_NORMAL_COORDS	= 2,
-	VBM_COLOR_COORDS	= 4
-};
-
-} // namespace crown
-

+ 0 - 67
engine/renderers/VertexFormat.cpp

@@ -1,67 +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 "VertexFormat.h"
-
-namespace crown
-{
-
-//-----------------------------------------------------------------------------
-size_t Vertex::bits_per_vertex(VertexFormat format)
-{
-	return bytes_per_vertex(format) * 8;
-}
-
-//-----------------------------------------------------------------------------
-size_t Vertex::bytes_per_vertex(VertexFormat format)
-{
-	switch (format)
-	{
-		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:
-		{
-			return 12;
-		}
-		case VF_XYZ_UV_XYZ_NORMAL_FLOAT_32:
-		{
-			return 32;
-		}
-		default:
-		{
-			return 0;
-		}
-	}
-}
-
-} // 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

+ 412 - 843
engine/renderers/gl/GLRenderer.cpp

@@ -24,1008 +24,577 @@ 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)
+const GLenum PRIMITIVE_TYPE_TABLE[] =
 {
-	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";
-	}
-}
+	GL_TRIANGLES,
+	GL_POINTS,
+	GL_LINES
+};
 
 //-----------------------------------------------------------------------------
-#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)
+const GLenum TEXTURE_MIN_FILTER_TABLE[] =
 {
-	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();
-}
+	0, // Unused
+	GL_NEAREST,
+	GL_LINEAR,
+	GL_NEAREST_MIPMAP_LINEAR,
+	GL_LINEAR_MIPMAP_LINEAR
+};
 
 //-----------------------------------------------------------------------------
-GLRenderer::~GLRenderer()
+const GLenum TEXTURE_MAG_FILTER_TABLE[] =
 {
-}
+	0, // Unused
+	GL_NEAREST,
+	GL_LINEAR,
+	GL_LINEAR,
+	GL_LINEAR
+};
 
 //-----------------------------------------------------------------------------
-void GLRenderer::init()
+const GLenum TEXTURE_WRAP_TABLE[] =
 {
-	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));
+	0, // Unused
+	GL_CLAMP_TO_EDGE,
+	GL_REPEAT
+};
 
-	// 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()
+// Keep in sync with ShaderAttrib
+const char* const SHADER_ATTRIB_NAMES[ATTRIB_COUNT] =
 {
-	unload_default_shaders();
-
-	m_context.destroy_context();
-}
+	"a_position",
+	"a_normal",
+	"a_color",
+	"a_tex_coord0",
+	"a_tex_coord1",
+	"a_tex_coord2",
+	"a_tex_coord3"
+};
 
-//-----------------------------------------------------------------------------
-VertexBufferId GLRenderer::create_vertex_buffer(size_t count, VertexFormat format, const void* vertices)
+const char* const SHADER_UNIFORM_NAMES[] =
 {
-	const VertexBufferId id = m_vertex_buffers_id_table.create();
-
-	VertexBuffer& buffer = m_vertex_buffers[id.index];
+	"u_view",
+	"u_model",
+	"u_model_view",
+	"u_model_view_projection",
+	"u_time_since_start"
+};
 
-	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 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 GLRenderer::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 GLRenderer::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 GLRenderer::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 GLRenderer::destroy_index_buffer(IndexBufferId id)
+const size_t UNIFORM_SIZE_TABLE[UNIFORM_END] =
 {
-	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));
+	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
+};
 
-	m_index_buffers_id_table.destroy(id);
-}
-
-//-----------------------------------------------------------------------------
-TextureId GLRenderer::create_texture(uint32_t width, uint32_t height, PixelFormat format, const void* data)
+ShaderUniform name_to_stock_uniform(const char* uniform)
 {
-	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,
-				 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)
-{
-	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, GL::pixel_format(gl_texture.format),
-					GL_UNSIGNED_BYTE, data));
-}
-
-//-----------------------------------------------------------------------------
-void GLRenderer::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 GLRenderer::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)
+	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;
+	return UNIFORM_COUNT;
 }
 
-//-----------------------------------------------------------------------------
-void GLRenderer::destroy_vertex_shader(VertexShaderId id)
+/// OpenGL renderer
+class RendererImplementation
 {
-	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 GLRenderer::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));
+public:
 
-	GL_CHECK(glCompileShader(gl_shader.gl_object));
-
-	GLint success;
-	GL_CHECK(glGetShaderiv(gl_shader.gl_object, GL_COMPILE_STATUS, &success));
-
-	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));
+				}
+			}
+
+			// 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 | STATE_CULL_CCW))
+			{
+				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]));
+		GL_CHECK(glFinish());
+		m_gl_context.swap_buffers();
 	}
-	else
-	{
-		GL_CHECK(glDisable(m_texture_unit_target[unit]));
-	}
-}
 
-//-----------------------------------------------------------------------------
-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);
-
-	GL_CHECK(glBlendEquation(gl_equation));
-
-	GLenum gl_src_factor = GL::blend_function(src);
-	GLenum gl_dst_factor = GL::blend_function(dst);
+	m_impl->render(*m_draw);
 
-	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
-

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

@@ -26,252 +26,528 @@ 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;
+extern const GLenum TEXTURE_MIN_FILTER_TABLE[];
+extern const GLenum TEXTURE_MAG_FILTER_TABLE[];
+extern const GLenum TEXTURE_WRAP_TABLE[];
+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 Texture
+static const char* gl_error_to_string(GLenum error)
 {
-	GLuint				gl_object;
-	PixelFormat			format;
-};
+	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
 
 //-----------------------------------------------------------------------------
 struct VertexBuffer
 {
-	GLuint				gl_object;
-	size_t				count;
-	VertexFormat		format;
+	//-----------------------------------------------------------------------------
+	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));
+	}
+
+public:
+
+	GLuint			m_id;
+	size_t			m_count;
+	VertexFormat	m_format;
 };
 
 //-----------------------------------------------------------------------------
 struct IndexBuffer
 {
-	GLuint				gl_object;
-	uint32_t			index_count;
+	//-----------------------------------------------------------------------------
+	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));
+	}
+
+public:
+
+	GLuint		m_id;
+	uint32_t	m_index_count;
 };
 
 //-----------------------------------------------------------------------------
-struct RenderBuffer
+struct Uniform
 {
-	GLuint				gl_frame_buffer;
-	GLuint				gl_render_buffer;
+	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);
+	}
+
+public:
+
+	char m_name[CROWN_MAX_UNIFORM_NAME_LENGTH];
+	UniformType m_type;
+	uint8_t m_num;
+	void* m_data;
 };
 
 //-----------------------------------------------------------------------------
-struct VertexShader
+struct Shader
 {
-	GLuint				gl_object;
+	//-----------------------------------------------------------------------------
+	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));
+	}
+
+public:
+
+	GLuint m_id;
 };
 
 //-----------------------------------------------------------------------------
-struct PixelShader
+struct Texture
 {
-	GLuint				gl_object;
+	//-----------------------------------------------------------------------------
+	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
+
+		// FIXME
+		GL_CHECK(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0,
+					 			GL_RGB, 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);
+	}
+
+public:
+
+	GLuint			m_id;
+	GLenum			m_target;      // Always GL_TEXTURE_2D
+	uint32_t		m_width;
+	uint32_t		m_height;
+	PixelFormat		m_format;
 };
 
 //-----------------------------------------------------------------------------
 struct GPUProgram
 {
-	GLuint				gl_object;
-};
+	//-----------------------------------------------------------------------------
+	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);
+		}
+
+		// 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;
+			}
+		}
+	}
 
-/// 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;
+	GLuint				m_id;
 
-	// Frame buffers
-	// RenderBufferId	create_render_buffer(uint32_t width, uint32_t height, PixelFormat format);
-	// void				destroy_render_buffer(RenderBufferId id);
+	uint8_t				m_num_active_attribs;
+	ShaderAttrib		m_active_attribs[ATTRIB_COUNT];
+	GLint				m_attrib_locations[ATTRIB_COUNT];
 
-	void				frame();
+	uint8_t				m_num_stock_uniforms;
+	ShaderUniform		m_stock_uniforms[UNIFORM_COUNT];
+	GLint				m_stock_uniform_locations[UNIFORM_COUNT];
 
-	void				set_clear_color(const Color4& color);
+	struct LocAndData
+	{
+		GLint loc;
+		void* data;
+	};
 
-	// 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];
+	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 - 113
engine/renderers/gl/GLUtils.cpp

@@ -1,113 +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 "GLUtils.h"
-
-namespace crown
-{
-
-//-----------------------------------------------------------------------------
-const GLenum GL::COMPARE_FUNCTION_TABLE[CF_COUNT] =
-{
-	GL_NEVER,
-	GL_LESS,
-	GL_EQUAL,
-	GL_LEQUAL,
-	GL_GREATER,
-	GL_NOTEQUAL,
-	GL_GEQUAL,
-	GL_ALWAYS
-};
-
-//-----------------------------------------------------------------------------
-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
-};
-
-//-----------------------------------------------------------------------------
-const GLenum GL::BLEND_EQUATION_TABLE[BE_COUNT] =
-{
-	GL_FUNC_ADD,
-	GL_FUNC_SUBTRACT,
-	GL_FUNC_REVERSE_SUBTRACT,
-	GL_MIN,
-	GL_MAX
-};
-
-//-----------------------------------------------------------------------------
-const GLenum GL::TEXTURE_WRAP_TABLE[TW_COUNT] =
-{
-	GL_REPEAT,
-	GL_CLAMP,
-	GL_CLAMP_TO_EDGE,
-	GL_CLAMP_TO_BORDER
-};
-
-//-----------------------------------------------------------------------------
-const GLenum GL::TEXTURE_MIN_FILTER_TABLE[TF_COUNT] =
-{
-	GL_NEAREST,
-	GL_LINEAR,
-	GL_NEAREST_MIPMAP_LINEAR,
-	GL_LINEAR_MIPMAP_LINEAR,
-	GL_LINEAR_MIPMAP_LINEAR
-};
-
-//-----------------------------------------------------------------------------
-const GLenum GL::TEXTURE_MAG_FILTER_TABLE[TF_COUNT] =
-{
-	GL_NEAREST,
-	GL_LINEAR,
-	GL_LINEAR,
-	GL_LINEAR,
-	GL_LINEAR
-};
-
-//-----------------------------------------------------------------------------
-const GLenum GL::POLYGON_MODE_TABLE[PM_COUNT] =
-{
-	GL_POINT,
-	GL_LINE,
-	GL_FILL
-};
-
-} // 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
-

+ 1 - 0
engine/renderers/gles/egl/GLContext.cpp → engine/renderers/gl/egl/GLContext.cpp

@@ -127,6 +127,7 @@ void GLContext::destroy_context()
 	EGL_CHECK(eglDestroyContext(display, context));
 	EGL_CHECK(eglDestroySurface(display, surface));
 	EGL_CHECK(eglTerminate(display));
+    display = EGL_NO_DISPLAY;
 
 	Log::i("EGL context destroyed");
 }

+ 5 - 0
engine/renderers/gles/egl/GLContext.h → engine/renderers/gl/egl/GLContext.h

@@ -41,6 +41,11 @@ public:
 
 	void			swap_buffers();
 
+	bool is_valid()
+	{
+		return display != EGL_NO_DISPLAY;
+	}
+
 private:
 
 	EGLDisplay 		display;

+ 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 - 971
engine/renderers/gles/GLESRenderer.cpp

@@ -1,971 +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() :
-	Renderer(),
-
-	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.");
-}
-
-//-----------------------------------------------------------------------------
-void GLESRenderer::shutdown()
-{
-	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));
-	GL_CHECK(glClearColor(0.5f, 0.5f, 0.5f, 0.5f));
-
-	// 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 - 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

+ 33 - 2
engine/resource/MeshResource.h

@@ -29,13 +29,36 @@ 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
 {
 
+//
+// 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;
 
@@ -56,6 +79,10 @@ public:
 	{
 		File* file = bundle.open(id);
 
+		(void)allocator;
+		(void)bundle;
+		(void)id;
+
 		MeshResource* resource = (MeshResource*)allocator.allocate(sizeof(MeshResource));
 		file->read(&resource->m_header, sizeof(MeshHeader));
 
@@ -80,8 +107,12 @@ public:
 	}
 
 	//-----------------------------------------------------------------------------
-	static void unload(Allocator& , void* )
+	static void unload(Allocator& a, void* res)
 	{
+		MeshResource* resource = (MeshResource*)res;
+		a.deallocate(resource->m_indices);
+		a.deallocate(resource->m_vertices);
+		a.deallocate(resource);
 	}
 
 	//-----------------------------------------------------------------------------

+ 1 - 1
engine/resource/Resource.h

@@ -44,7 +44,7 @@ const char* const CONFIG_EXTENSION			= "config";
 const char* const PACKAGE_EXTENSION			= "package";
 
 const uint32_t TEXTURE_TYPE					= 0xDEED4F7;
-const uint32_t MESH_TYPE					= 0xA6E48B29;
+const uint32_t MESH_TYPE					= 0x742FBC9A;
 const uint32_t LUA_TYPE						= 0xD96E7C37;
 const uint32_t TEXT_TYPE					= 0x45CC650;
 const uint32_t MATERIAL_TYPE				= 0x46807A92;

+ 18 - 9
engine/resource/ResourceLoader.cpp

@@ -34,6 +34,7 @@ namespace crown
 //-----------------------------------------------------------------------------
 ResourceLoader::ResourceLoader(Bundle& bundle, Allocator& resource_heap) :
 	m_thread("resource-loader"),
+	m_should_run(false),
 	m_bundle(bundle),
 	m_resource_heap(resource_heap),
 	m_num_requests(0),
@@ -94,25 +95,33 @@ void* ResourceLoader::load_resource_data(LoadResourceId id) const
 //-----------------------------------------------------------------------------
 int32_t ResourceLoader::run()
 {
-	while (m_thread.is_running())
+	while (m_should_run)
 	{
 		m_requests_mutex.lock();
-		while (m_requests.empty())
+		while (m_requests.empty() && m_should_run)
 		{
 			m_full.wait(m_requests_mutex);
 		}
 
-		LoadResource request = m_requests.front();
-		m_requests.pop_front();
+		if (m_should_run)
+		{
+			LoadResource request = m_requests.front();
+			m_requests.pop_front();
 
-		m_requests_mutex.unlock();
+			m_requests_mutex.unlock();
 
-		m_results[request.id % MAX_LOAD_REQUESTS].status = LRS_LOADING;
+			m_results[request.id % MAX_LOAD_REQUESTS].status = LRS_LOADING;
 
-		void* data = resource_on_load(request.type, m_resource_heap, m_bundle, request.resource);
+			void* data = resource_on_load(request.type, m_resource_heap, m_bundle, request.resource);
 
-		m_results[request.id % MAX_LOAD_REQUESTS].data = data;
-		m_results[request.id % MAX_LOAD_REQUESTS].status = LRS_LOADED;
+			m_results[request.id % MAX_LOAD_REQUESTS].data = data;
+			m_results[request.id % MAX_LOAD_REQUESTS].status = LRS_LOADED;
+		}
+		else
+		{
+			// Release the mutex when exiting
+			m_requests_mutex.unlock();
+		}
 	}
 
 	return 0;

+ 4 - 0
engine/resource/ResourceLoader.h

@@ -88,11 +88,14 @@ public:
 
 	void start()
 	{
+		m_should_run = true;
 		m_thread.start(background_run, this);
 	}
 
 	void stop()
 	{
+		m_should_run = false;
+		m_full.signal();
 		m_thread.stop();
 	}
 
@@ -106,6 +109,7 @@ private:
 private:
 
 	Thread					m_thread;
+	bool					m_should_run;
 
 	// Whether to look for resources
 	Bundle&					m_bundle;

+ 0 - 1
engine/resource/TextureResource.h

@@ -29,7 +29,6 @@ OTHER DEALINGS IN THE SOFTWARE.
 #include "Types.h"
 #include "Resource.h"
 #include "PixelFormat.h"
-#include "Texture.h"
 #include "Bundle.h"
 #include "Allocator.h"
 #include "File.h"

+ 135 - 0
utils/code-cleaner.rb

@@ -0,0 +1,135 @@
+# 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.
+
+require 'optparse'
+require 'ostruct'
+
+$extension = [".cpp", ".h"]
+
+$files_list = Array.new
+
+#------------------------------------------------------------------------------
+def validate_command_line(args)
+
+	if args.length != 2
+		return false
+	end
+
+	if args[0] != "--path"
+		return false
+	end
+
+	return true
+end
+
+#------------------------------------------------------------------------------
+def parse_command_line(args)
+
+	banner = "Usage: crown-android.rb --target <android-target> --name <project-name> --path <project-path>\n"
+
+	if not validate_command_line(args)
+		print banner
+		exit
+	end
+
+	options = OpenStruct.new
+
+	OptionParser.new do |opts|
+		opts.banner = banner
+
+		opts.on("-p", "--path PATH", "Code Path to clean") do |p|
+			options.path = p
+		end
+
+	    opts.on_tail("-h", "--help", "Show this message") do
+	    	puts opts
+	      	exit
+	    end
+	end.parse!(args)
+
+	return options
+
+end
+	
+#------------------------------------------------------------------------------
+def lists_files(path)
+
+	files = Dir.entries(path)
+
+	for entry in files
+		if entry == "." || entry == ".."
+			next
+		end
+
+		tmp = path + '/' + entry
+
+		if File.directory?(tmp)
+			lists_files(tmp)
+		elsif File.file?(tmp)
+			ext = File.extname(tmp)
+			if ext == $extension[0] || ext == $extension[1] || ext == $extension[2]
+				$files_list.push(tmp);
+			end
+		end
+	end
+	
+end
+
+#------------------------------------------------------------------------------
+def clean_file(file_name) 
+	lines = []
+	# Copies each file's line
+	File.open(file_name) do |file|
+		file.each_line do |line|
+			lines << line
+		end
+	end
+
+	clean = true
+	lines.each_index do |index|
+		line = lines[index]
+		#match one or more spaces/tabs at the end of the line -> nothing
+		new_line = line.gsub(/[ \t]+$/, "")
+		if(new_line != line)
+			if(clean)
+	    		puts "Cleaning '#{file_name}'"
+	    		clean = false
+	  		end
+
+	  		lines[index] = new_line
+		end
+	end
+
+	if(!clean)
+		File.open(file_name, 'w') do |file|
+		lines.each { |line| file.write(line) }
+		end
+	end
+end
+
+opts = parse_command_line(ARGV)
+
+lists_files(opts.path)
+
+$files_list.each { |file| clean_file(file) }