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

-Restored multithread capability to VisualServer
-Restored resource previews!

Juan Linietsky пре 8 година
родитељ
комит
612ab8fcdb

+ 83 - 0
core/command_queue_mt.h

@@ -170,6 +170,43 @@ class CommandQueueMT {
 		virtual void call() { (instance->*method)(p1, p2, p3, p4, p5, p6, p7, p8); }
 		virtual void call() { (instance->*method)(p1, p2, p3, p4, p5, p6, p7, p8); }
 	};
 	};
 
 
+	template <class T, class M, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8, class P9>
+	struct Command9 : public CommandBase {
+
+		T *instance;
+		M method;
+		typename GetSimpleTypeT<P1>::type_t p1;
+		typename GetSimpleTypeT<P2>::type_t p2;
+		typename GetSimpleTypeT<P3>::type_t p3;
+		typename GetSimpleTypeT<P4>::type_t p4;
+		typename GetSimpleTypeT<P5>::type_t p5;
+		typename GetSimpleTypeT<P6>::type_t p6;
+		typename GetSimpleTypeT<P7>::type_t p7;
+		typename GetSimpleTypeT<P8>::type_t p8;
+		typename GetSimpleTypeT<P9>::type_t p9;
+
+		virtual void call() { (instance->*method)(p1, p2, p3, p4, p5, p6, p7, p8, p9); }
+	};
+
+	template <class T, class M, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8, class P9, class P10>
+	struct Command10 : public CommandBase {
+
+		T *instance;
+		M method;
+		typename GetSimpleTypeT<P1>::type_t p1;
+		typename GetSimpleTypeT<P2>::type_t p2;
+		typename GetSimpleTypeT<P3>::type_t p3;
+		typename GetSimpleTypeT<P4>::type_t p4;
+		typename GetSimpleTypeT<P5>::type_t p5;
+		typename GetSimpleTypeT<P6>::type_t p6;
+		typename GetSimpleTypeT<P7>::type_t p7;
+		typename GetSimpleTypeT<P8>::type_t p8;
+		typename GetSimpleTypeT<P9>::type_t p9;
+		typename GetSimpleTypeT<P10>::type_t p10;
+
+		virtual void call() { (instance->*method)(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10); }
+	};
+
 	/* comands that return */
 	/* comands that return */
 
 
 	template <class T, class M, class R>
 	template <class T, class M, class R>
@@ -779,6 +816,52 @@ public:
 
 
 		if (sync) sync->post();
 		if (sync) sync->post();
 	}
 	}
+
+	template <class T, class M, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8, class P9>
+	void push(T *p_instance, M p_method, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8, P9 p9) {
+
+		Command9<T, M, P1, P2, P3, P4, P5, P6, P7, P8, P9> *cmd = allocate_and_lock<Command9<T, M, P1, P2, P3, P4, P5, P6, P7, P8, P9> >();
+
+		cmd->instance = p_instance;
+		cmd->method = p_method;
+		cmd->p1 = p1;
+		cmd->p2 = p2;
+		cmd->p3 = p3;
+		cmd->p4 = p4;
+		cmd->p5 = p5;
+		cmd->p6 = p6;
+		cmd->p7 = p7;
+		cmd->p8 = p8;
+		cmd->p9 = p9;
+
+		unlock();
+
+		if (sync) sync->post();
+	}
+
+	template <class T, class M, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8, class P9, class P10>
+	void push(T *p_instance, M p_method, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8, P9 p9, P10 p10) {
+
+		Command10<T, M, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10> *cmd = allocate_and_lock<Command10<T, M, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10> >();
+
+		cmd->instance = p_instance;
+		cmd->method = p_method;
+		cmd->p1 = p1;
+		cmd->p2 = p2;
+		cmd->p3 = p3;
+		cmd->p4 = p4;
+		cmd->p5 = p5;
+		cmd->p6 = p6;
+		cmd->p7 = p7;
+		cmd->p8 = p8;
+		cmd->p9 = p9;
+		cmd->p10 = p10;
+
+		unlock();
+
+		if (sync) sync->post();
+	}
+
 	/*** PUSH AND RET COMMANDS ***/
 	/*** PUSH AND RET COMMANDS ***/
 
 
 	template <class T, class M, class R>
 	template <class T, class M, class R>

+ 8 - 8
core/image.cpp

@@ -81,21 +81,21 @@ const char *Image::format_names[Image::FORMAT_MAX] = {
 
 
 SavePNGFunc Image::save_png_func = NULL;
 SavePNGFunc Image::save_png_func = NULL;
 
 
-void Image::_put_pixelb(int p_x, int p_y, uint32_t p_pixelsize, uint8_t *p_dst, const uint8_t *p_src) {
+void Image::_put_pixelb(int p_x, int p_y, uint32_t p_pixelsize, uint8_t *p_data, const uint8_t *p_pixel) {
 
 
 	uint32_t ofs = (p_y * width + p_x) * p_pixelsize;
 	uint32_t ofs = (p_y * width + p_x) * p_pixelsize;
 
 
 	for (uint32_t i = 0; i < p_pixelsize; i++) {
 	for (uint32_t i = 0; i < p_pixelsize; i++) {
-		p_dst[ofs + i] = p_src[i];
+		p_data[ofs + i] = p_pixel[i];
 	}
 	}
 }
 }
 
 
-void Image::_get_pixelb(int p_x, int p_y, uint32_t p_pixelsize, const uint8_t *p_src, uint8_t *p_dst) {
+void Image::_get_pixelb(int p_x, int p_y, uint32_t p_pixelsize, const uint8_t *p_data, uint8_t *p_pixel) {
 
 
 	uint32_t ofs = (p_y * width + p_x) * p_pixelsize;
 	uint32_t ofs = (p_y * width + p_x) * p_pixelsize;
 
 
 	for (uint32_t i = 0; i < p_pixelsize; i++) {
 	for (uint32_t i = 0; i < p_pixelsize; i++) {
-		p_dst[i] = p_src[ofs + i];
+		p_pixel[i] = p_data[ofs + i];
 	}
 	}
 }
 }
 
 
@@ -818,7 +818,7 @@ void Image::flip_y() {
 		uint8_t down[16];
 		uint8_t down[16];
 		uint32_t pixel_size = get_format_pixel_size(format);
 		uint32_t pixel_size = get_format_pixel_size(format);
 
 
-		for (int y = 0; y < height; y++) {
+		for (int y = 0; y < height / 2; y++) {
 
 
 			for (int x = 0; x < width; x++) {
 			for (int x = 0; x < width; x++) {
 
 
@@ -854,7 +854,7 @@ void Image::flip_x() {
 
 
 		for (int y = 0; y < height; y++) {
 		for (int y = 0; y < height; y++) {
 
 
-			for (int x = 0; x < width; x++) {
+			for (int x = 0; x < width / 2; x++) {
 
 
 				_get_pixelb(x, y, pixel_size, w.ptr(), up);
 				_get_pixelb(x, y, pixel_size, w.ptr(), up);
 				_get_pixelb(width - x - 1, y, pixel_size, w.ptr(), down);
 				_get_pixelb(width - x - 1, y, pixel_size, w.ptr(), down);
@@ -1457,7 +1457,7 @@ Error Image::save_png(const String &p_path) const {
 	if (save_png_func == NULL)
 	if (save_png_func == NULL)
 		return ERR_UNAVAILABLE;
 		return ERR_UNAVAILABLE;
 
 
-	return save_png_func(p_path, Ref<Image>(this));
+	return save_png_func(p_path, Ref<Image>((Image *)this));
 }
 }
 
 
 int Image::get_image_data_size(int p_width, int p_height, Format p_format, int p_mipmaps) {
 int Image::get_image_data_size(int p_width, int p_height, Format p_format, int p_mipmaps) {
@@ -1599,7 +1599,7 @@ Rect2 Image::get_used_rect() const {
 Ref<Image> Image::get_rect(const Rect2 &p_area) const {
 Ref<Image> Image::get_rect(const Rect2 &p_area) const {
 
 
 	Ref<Image> img = memnew(Image(p_area.size.x, p_area.size.y, mipmaps, format));
 	Ref<Image> img = memnew(Image(p_area.size.x, p_area.size.y, mipmaps, format));
-	img->blit_rect(Ref<Image>(this), p_area, Point2(0, 0));
+	img->blit_rect(Ref<Image>((Image *)this), p_area, Point2(0, 0));
 	return img;
 	return img;
 }
 }
 
 

+ 2 - 2
core/image.h

@@ -162,8 +162,8 @@ private:
 	static int _get_dst_image_size(int p_width, int p_height, Format p_format, int &r_mipmaps, int p_mipmaps = -1);
 	static int _get_dst_image_size(int p_width, int p_height, Format p_format, int &r_mipmaps, int p_mipmaps = -1);
 	bool _can_modify(Format p_format) const;
 	bool _can_modify(Format p_format) const;
 
 
-	_FORCE_INLINE_ void _put_pixelb(int p_x, int p_y, uint32_t p_pixelsize, uint8_t *p_dst, const uint8_t *p_src);
-	_FORCE_INLINE_ void _get_pixelb(int p_x, int p_y, uint32_t p_pixelsize, const uint8_t *p_src, uint8_t *p_dst);
+	_FORCE_INLINE_ void _put_pixelb(int p_x, int p_y, uint32_t p_pixelsize, uint8_t *p_data, const uint8_t *p_pixel);
+	_FORCE_INLINE_ void _get_pixelb(int p_x, int p_y, uint32_t p_pixelsize, const uint8_t *p_data, uint8_t *p_pixel);
 
 
 	void _set_data(const Dictionary &p_data);
 	void _set_data(const Dictionary &p_data);
 	Dictionary _get_data() const;
 	Dictionary _get_data() const;

+ 6 - 6
core/object.cpp

@@ -1831,10 +1831,10 @@ void postinitialize_handler(Object *p_object) {
 	p_object->_postinitialize();
 	p_object->_postinitialize();
 }
 }
 
 
-HashMap<uint32_t, Object *> ObjectDB::instances;
-uint32_t ObjectDB::instance_counter = 1;
+HashMap<ObjectID, Object *> ObjectDB::instances;
+ObjectID ObjectDB::instance_counter = 1;
 HashMap<Object *, ObjectID, ObjectDB::ObjectPtrHash> ObjectDB::instance_checks;
 HashMap<Object *, ObjectID, ObjectDB::ObjectPtrHash> ObjectDB::instance_checks;
-uint32_t ObjectDB::add_instance(Object *p_object) {
+ObjectID ObjectDB::add_instance(Object *p_object) {
 
 
 	ERR_FAIL_COND_V(p_object->get_instance_ID() != 0, 0);
 	ERR_FAIL_COND_V(p_object->get_instance_ID() != 0, 0);
 
 
@@ -1859,7 +1859,7 @@ void ObjectDB::remove_instance(Object *p_object) {
 
 
 	rw_lock->write_unlock();
 	rw_lock->write_unlock();
 }
 }
-Object *ObjectDB::get_instance(uint32_t p_instance_ID) {
+Object *ObjectDB::get_instance(ObjectID p_instance_ID) {
 
 
 	rw_lock->read_lock();
 	rw_lock->read_lock();
 	Object **obj = instances.getptr(p_instance_ID);
 	Object **obj = instances.getptr(p_instance_ID);
@@ -1874,7 +1874,7 @@ void ObjectDB::debug_objects(DebugFunc p_func) {
 
 
 	rw_lock->read_lock();
 	rw_lock->read_lock();
 
 
-	const uint32_t *K = NULL;
+	const ObjectID *K = NULL;
 	while ((K = instances.next(K))) {
 	while ((K = instances.next(K))) {
 
 
 		p_func(instances[*K]);
 		p_func(instances[*K]);
@@ -1909,7 +1909,7 @@ void ObjectDB::cleanup() {
 
 
 		WARN_PRINT("ObjectDB Instances still exist!");
 		WARN_PRINT("ObjectDB Instances still exist!");
 		if (OS::get_singleton()->is_stdout_verbose()) {
 		if (OS::get_singleton()->is_stdout_verbose()) {
-			const uint32_t *K = NULL;
+			const ObjectID *K = NULL;
 			while ((K = instances.next(K))) {
 			while ((K = instances.next(K))) {
 
 
 				String node_name;
 				String node_name;

+ 6 - 6
core/object.h

@@ -350,7 +350,7 @@ public:                                                        \
 private:
 private:
 
 
 class ScriptInstance;
 class ScriptInstance;
-typedef uint32_t ObjectID;
+typedef uint64_t ObjectID;
 
 
 class Object {
 class Object {
 public:
 public:
@@ -423,7 +423,7 @@ private:
 	bool _block_signals;
 	bool _block_signals;
 	int _predelete_ok;
 	int _predelete_ok;
 	Set<Object *> change_receptors;
 	Set<Object *> change_receptors;
-	uint32_t _instance_ID;
+	ObjectID _instance_ID;
 	bool _predelete();
 	bool _predelete();
 	void _postinitialize();
 	void _postinitialize();
 	bool _can_translate;
 	bool _can_translate;
@@ -690,16 +690,16 @@ class ObjectDB {
 		}
 		}
 	};
 	};
 
 
-	static HashMap<uint32_t, Object *> instances;
+	static HashMap<ObjectID, Object *> instances;
 	static HashMap<Object *, ObjectID, ObjectPtrHash> instance_checks;
 	static HashMap<Object *, ObjectID, ObjectPtrHash> instance_checks;
 
 
-	static uint32_t instance_counter;
+	static ObjectID instance_counter;
 	friend class Object;
 	friend class Object;
 	friend void unregister_core_types();
 	friend void unregister_core_types();
 
 
 	static RWLock *rw_lock;
 	static RWLock *rw_lock;
 	static void cleanup();
 	static void cleanup();
-	static uint32_t add_instance(Object *p_object);
+	static ObjectID add_instance(Object *p_object);
 	static void remove_instance(Object *p_object);
 	static void remove_instance(Object *p_object);
 	friend void register_core_types();
 	friend void register_core_types();
 	static void setup();
 	static void setup();
@@ -707,7 +707,7 @@ class ObjectDB {
 public:
 public:
 	typedef void (*DebugFunc)(Object *p_obj);
 	typedef void (*DebugFunc)(Object *p_obj);
 
 
-	static Object *get_instance(uint32_t p_instance_ID);
+	static Object *get_instance(ObjectID p_instance_ID);
 	static void debug_objects(DebugFunc p_func);
 	static void debug_objects(DebugFunc p_func);
 	static int get_object_count();
 	static int get_object_count();
 
 

+ 17 - 21
drivers/gles3/rasterizer_scene_gles3.cpp

@@ -1783,13 +1783,6 @@ void RasterizerSceneGLES3::_set_cull(bool p_front, bool p_reverse_cull) {
 
 
 void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements, int p_element_count, const Transform &p_view_transform, const CameraMatrix &p_projection, GLuint p_base_env, bool p_reverse_cull, bool p_alpha_pass, bool p_shadow, bool p_directional_add, bool p_directional_shadows) {
 void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements, int p_element_count, const Transform &p_view_transform, const CameraMatrix &p_projection, GLuint p_base_env, bool p_reverse_cull, bool p_alpha_pass, bool p_shadow, bool p_directional_add, bool p_directional_shadows) {
 
 
-	if (storage->frame.current_rt && storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_VFLIP]) {
-		//p_reverse_cull=!p_reverse_cull;
-		glFrontFace(GL_CCW);
-	} else {
-		glFrontFace(GL_CW);
-	}
-
 	glBindBufferBase(GL_UNIFORM_BUFFER, 0, state.scene_ubo); //bind globals ubo
 	glBindBufferBase(GL_UNIFORM_BUFFER, 0, state.scene_ubo); //bind globals ubo
 
 
 	if (!p_shadow && !p_directional_add) {
 	if (!p_shadow && !p_directional_add) {
@@ -3306,19 +3299,21 @@ void RasterizerSceneGLES3::_post_process(Environment *env, const CameraMatrix &p
 	glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
 	glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
 	glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
 	glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
 
 
-	if (!env) {
-		//no environment, simply return and convert to SRGB
+	if (!env || storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT]) {
+		//no environment or transparent render, simply return and convert to SRGB
 		glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->fbo);
 		glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->fbo);
 		glActiveTexture(GL_TEXTURE0);
 		glActiveTexture(GL_TEXTURE0);
 		glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->effects.mip_maps[0].color);
 		glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->effects.mip_maps[0].color);
 		storage->shaders.copy.set_conditional(CopyShaderGLES3::LINEAR_TO_SRGB, true);
 		storage->shaders.copy.set_conditional(CopyShaderGLES3::LINEAR_TO_SRGB, true);
-		storage->shaders.copy.set_conditional(CopyShaderGLES3::DISABLE_ALPHA, true);
+		storage->shaders.copy.set_conditional(CopyShaderGLES3::V_FLIP, storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_VFLIP]);
+		storage->shaders.copy.set_conditional(CopyShaderGLES3::DISABLE_ALPHA, !storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT]);
 		storage->shaders.copy.bind();
 		storage->shaders.copy.bind();
 
 
 		_copy_screen();
 		_copy_screen();
 
 
 		storage->shaders.copy.set_conditional(CopyShaderGLES3::LINEAR_TO_SRGB, false);
 		storage->shaders.copy.set_conditional(CopyShaderGLES3::LINEAR_TO_SRGB, false);
 		storage->shaders.copy.set_conditional(CopyShaderGLES3::DISABLE_ALPHA, false); //compute luminance
 		storage->shaders.copy.set_conditional(CopyShaderGLES3::DISABLE_ALPHA, false); //compute luminance
+		storage->shaders.copy.set_conditional(CopyShaderGLES3::V_FLIP, false);
 
 
 		return;
 		return;
 	}
 	}
@@ -3692,6 +3687,7 @@ void RasterizerSceneGLES3::_post_process(Environment *env, const CameraMatrix &p
 		}
 		}
 	}
 	}
 
 
+	state.tonemap_shader.set_conditional(TonemapShaderGLES3::V_FLIP, storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_VFLIP]);
 	state.tonemap_shader.bind();
 	state.tonemap_shader.bind();
 
 
 	state.tonemap_shader.set_uniform(TonemapShaderGLES3::EXPOSURE, env->tone_mapper_exposure);
 	state.tonemap_shader.set_uniform(TonemapShaderGLES3::EXPOSURE, env->tone_mapper_exposure);
@@ -3739,6 +3735,7 @@ void RasterizerSceneGLES3::_post_process(Environment *env, const CameraMatrix &p
 	state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_GLOW_FILTER_BICUBIC, false);
 	state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_GLOW_FILTER_BICUBIC, false);
 	state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_BCS, false);
 	state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_BCS, false);
 	state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_COLOR_CORRECTION, false);
 	state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_COLOR_CORRECTION, false);
+	state.tonemap_shader.set_conditional(TonemapShaderGLES3::V_FLIP, false);
 }
 }
 
 
 void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID p_environment, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass) {
 void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID p_environment, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass) {
@@ -3880,6 +3877,9 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const
 	} else {
 	} else {
 
 
 		use_mrt = env && (state.used_screen_texture || state.used_sss || env->ssao_enabled || env->ssr_enabled); //only enable MRT rendering if any of these is enabled
 		use_mrt = env && (state.used_screen_texture || state.used_sss || env->ssao_enabled || env->ssr_enabled); //only enable MRT rendering if any of these is enabled
+		//effects disabled and transparency also prevent using MRTs
+		use_mrt = use_mrt && !storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT];
+		use_mrt = use_mrt && !storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_NO_3D_EFFECTS];
 
 
 		glViewport(0, 0, storage->frame.current_rt->width, storage->frame.current_rt->height);
 		glViewport(0, 0, storage->frame.current_rt->width, storage->frame.current_rt->height);
 
 
@@ -3928,7 +3928,9 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const
 	RasterizerStorageGLES3::Sky *sky = NULL;
 	RasterizerStorageGLES3::Sky *sky = NULL;
 	GLuint env_radiance_tex = 0;
 	GLuint env_radiance_tex = 0;
 
 
-	if (!env || env->bg_mode == VS::ENV_BG_CLEAR_COLOR) {
+	if (storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT]) {
+		clear_color = Color(0, 0, 0, 0);
+	} else if (!env || env->bg_mode == VS::ENV_BG_CLEAR_COLOR) {
 
 
 		if (storage->frame.clear_request) {
 		if (storage->frame.clear_request) {
 
 
@@ -3961,20 +3963,14 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const
 
 
 	if (storage->frame.current_rt && storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT]) {
 	if (storage->frame.current_rt && storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT]) {
 		glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
 		glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+		glEnable(GL_BLEND);
 	} else {
 	} else {
 		glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
 		glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+		glDisable(GL_BLEND);
 	}
 	}
 
 
-	glDisable(GL_BLEND);
-
 	render_list.sort_by_key(false);
 	render_list.sort_by_key(false);
 
 
-	if (storage->frame.current_rt && storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT]) {
-		glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
-	} else {
-		glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-	}
-
 	if (state.directional_light_count == 0) {
 	if (state.directional_light_count == 0) {
 		directional_light = NULL;
 		directional_light = NULL;
 		_render_list(render_list.elements, render_list.element_count, p_cam_transform, p_cam_projection, env_radiance_tex, false, false, false, false, shadow_atlas != NULL);
 		_render_list(render_list.elements, render_list.element_count, p_cam_transform, p_cam_projection, env_radiance_tex, false, false, false, false, shadow_atlas != NULL);
@@ -3996,14 +3992,14 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const
 		glDrawBuffers(1, &gldb);
 		glDrawBuffers(1, &gldb);
 	}
 	}
 
 
-	if (env && env->bg_mode == VS::ENV_BG_SKY) {
+	if (env && env->bg_mode == VS::ENV_BG_SKY && !storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT]) {
 
 
 		/*
 		/*
 		if (use_mrt) {
 		if (use_mrt) {
 			glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->buffers.fbo); //switch to alpha fbo for sky, only diffuse/ambient matters
 			glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->buffers.fbo); //switch to alpha fbo for sky, only diffuse/ambient matters
 		*/
 		*/
 
 
-		_draw_sky(sky, p_cam_projection, p_cam_transform, storage->frame.current_rt && storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_VFLIP], env->sky_scale, env->bg_energy);
+		_draw_sky(sky, p_cam_projection, p_cam_transform, false, env->sky_scale, env->bg_energy);
 	}
 	}
 
 
 	//_render_list_forward(&alpha_render_list,camera_transform,camera_transform_inverse,camera_projection,false,fragment_lighting,true);
 	//_render_list_forward(&alpha_render_list,camera_transform,camera_transform_inverse,camera_projection,false,fragment_lighting,true);

+ 141 - 134
drivers/gles3/rasterizer_storage_gles3.cpp

@@ -782,7 +782,6 @@ void RasterizerStorageGLES3::texture_set_data(RID p_texture, const Ref<Image> &p
 			int bh = h;
 			int bh = h;
 
 
 			glCompressedTexImage2D(blit_target, i, internal_format, bw, bh, 0, size, &read[ofs]);
 			glCompressedTexImage2D(blit_target, i, internal_format, bw, bh, 0, size, &read[ofs]);
-			print_line("format: " + Image::get_format_name(texture->format) + " size: " + Vector2(bw, bh) + " block: " + itos(block));
 
 
 		} else {
 		} else {
 			glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
 			glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
@@ -825,8 +824,7 @@ Ref<Image> RasterizerStorageGLES3::texture_get_data(RID p_texture, VS::CubeMapSi
 
 
 	ERR_FAIL_COND_V(!texture, Ref<Image>());
 	ERR_FAIL_COND_V(!texture, Ref<Image>());
 	ERR_FAIL_COND_V(!texture->active, Ref<Image>());
 	ERR_FAIL_COND_V(!texture->active, Ref<Image>());
-	ERR_FAIL_COND_V(texture->data_size == 0, Ref<Image>());
-	ERR_FAIL_COND_V(texture->render_target, Ref<Image>());
+	ERR_FAIL_COND_V(texture->data_size == 0 && !texture->render_target, Ref<Image>());
 
 
 	if (!texture->images[p_cube_side].is_null()) {
 	if (!texture->images[p_cube_side].is_null()) {
 		return texture->images[p_cube_side];
 		return texture->images[p_cube_side];
@@ -5493,6 +5491,7 @@ void RasterizerStorageGLES3::_render_target_clear(RenderTarget *rt) {
 	tex->alloc_width = 0;
 	tex->alloc_width = 0;
 	tex->width = 0;
 	tex->width = 0;
 	tex->height = 0;
 	tex->height = 0;
+	tex->active = false;
 
 
 	for (int i = 0; i < 2; i++) {
 	for (int i = 0; i < 2; i++) {
 		for (int j = 0; j < rt->effects.mip_maps[i].sizes.size(); j++) {
 		for (int j = 0; j < rt->effects.mip_maps[i].sizes.size(); j++) {
@@ -5589,13 +5588,14 @@ void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt) {
 		tex->alloc_width = rt->width;
 		tex->alloc_width = rt->width;
 		tex->height = rt->height;
 		tex->height = rt->height;
 		tex->alloc_height = rt->height;
 		tex->alloc_height = rt->height;
+		tex->active = true;
 
 
 		texture_set_flags(rt->texture, tex->flags);
 		texture_set_flags(rt->texture, tex->flags);
 	}
 	}
 
 
 	/* BACK FBO */
 	/* BACK FBO */
 
 
-	if (config.render_arch == RENDER_ARCH_DESKTOP && !rt->flags[RENDER_TARGET_NO_3D]) {
+	if (!rt->flags[RENDER_TARGET_NO_3D]) {
 
 
 		static const int msaa_value[] = { 0, 2, 4, 8, 16 };
 		static const int msaa_value[] = { 0, 2, 4, 8, 16 };
 		int msaa = msaa_value[rt->msaa];
 		int msaa = msaa_value[rt->msaa];
@@ -5623,75 +5623,155 @@ void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt) {
 
 
 		glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rt->buffers.diffuse);
 		glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rt->buffers.diffuse);
 
 
-		glGenRenderbuffers(1, &rt->buffers.specular);
-		glBindRenderbuffer(GL_RENDERBUFFER, rt->buffers.specular);
+		if (!rt->flags[RENDER_TARGET_NO_3D_EFFECTS]) {
 
 
-		if (msaa == 0)
-			glRenderbufferStorage(GL_RENDERBUFFER, color_internal_format, rt->width, rt->height);
-		else
-			glRenderbufferStorageMultisample(GL_RENDERBUFFER, msaa, color_internal_format, rt->width, rt->height);
+			glGenRenderbuffers(1, &rt->buffers.specular);
+			glBindRenderbuffer(GL_RENDERBUFFER, rt->buffers.specular);
 
 
-		glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_RENDERBUFFER, rt->buffers.specular);
+			if (msaa == 0)
+				glRenderbufferStorage(GL_RENDERBUFFER, color_internal_format, rt->width, rt->height);
+			else
+				glRenderbufferStorageMultisample(GL_RENDERBUFFER, msaa, color_internal_format, rt->width, rt->height);
 
 
-		glGenRenderbuffers(1, &rt->buffers.normal_rough);
-		glBindRenderbuffer(GL_RENDERBUFFER, rt->buffers.normal_rough);
+			glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_RENDERBUFFER, rt->buffers.specular);
 
 
-		if (msaa == 0)
-			glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, rt->width, rt->height);
-		else
-			glRenderbufferStorageMultisample(GL_RENDERBUFFER, msaa, GL_RGBA8, rt->width, rt->height);
+			glGenRenderbuffers(1, &rt->buffers.normal_rough);
+			glBindRenderbuffer(GL_RENDERBUFFER, rt->buffers.normal_rough);
 
 
-		glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_RENDERBUFFER, rt->buffers.normal_rough);
+			if (msaa == 0)
+				glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, rt->width, rt->height);
+			else
+				glRenderbufferStorageMultisample(GL_RENDERBUFFER, msaa, GL_RGBA8, rt->width, rt->height);
 
 
-		glGenRenderbuffers(1, &rt->buffers.sss);
-		glBindRenderbuffer(GL_RENDERBUFFER, rt->buffers.sss);
+			glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_RENDERBUFFER, rt->buffers.normal_rough);
 
 
-		if (msaa == 0)
-			glRenderbufferStorage(GL_RENDERBUFFER, GL_R8, rt->width, rt->height);
-		else
-			glRenderbufferStorageMultisample(GL_RENDERBUFFER, msaa, GL_R8, rt->width, rt->height);
+			glGenRenderbuffers(1, &rt->buffers.sss);
+			glBindRenderbuffer(GL_RENDERBUFFER, rt->buffers.sss);
 
 
-		glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT3, GL_RENDERBUFFER, rt->buffers.sss);
+			if (msaa == 0)
+				glRenderbufferStorage(GL_RENDERBUFFER, GL_R8, rt->width, rt->height);
+			else
+				glRenderbufferStorageMultisample(GL_RENDERBUFFER, msaa, GL_R8, rt->width, rt->height);
 
 
-		GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
-		glBindFramebuffer(GL_FRAMEBUFFER, RasterizerStorageGLES3::system_fbo);
+			glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT3, GL_RENDERBUFFER, rt->buffers.sss);
 
 
-		if (status != GL_FRAMEBUFFER_COMPLETE) {
-			printf("err status: %x\n", status);
-			_render_target_clear(rt);
-			ERR_FAIL_COND(status != GL_FRAMEBUFFER_COMPLETE);
-		}
+			GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+			glBindFramebuffer(GL_FRAMEBUFFER, RasterizerStorageGLES3::system_fbo);
 
 
-		glBindRenderbuffer(GL_RENDERBUFFER, 0);
+			if (status != GL_FRAMEBUFFER_COMPLETE) {
+				printf("err status: %x\n", status);
+				_render_target_clear(rt);
+				ERR_FAIL_COND(status != GL_FRAMEBUFFER_COMPLETE);
+			}
 
 
-		// effect resolver
+			glBindRenderbuffer(GL_RENDERBUFFER, 0);
 
 
-		glGenFramebuffers(1, &rt->buffers.effect_fbo);
-		glBindFramebuffer(GL_FRAMEBUFFER, rt->buffers.effect_fbo);
+			// effect resolver
 
 
-		glGenTextures(1, &rt->buffers.effect);
-		glBindTexture(GL_TEXTURE_2D, rt->buffers.effect);
-		glTexImage2D(GL_TEXTURE_2D, 0, color_internal_format, rt->width, rt->height, 0,
-				color_format, color_type, NULL);
-		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
-		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-		glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
-				GL_TEXTURE_2D, rt->buffers.effect, 0);
+			glGenFramebuffers(1, &rt->buffers.effect_fbo);
+			glBindFramebuffer(GL_FRAMEBUFFER, rt->buffers.effect_fbo);
 
 
-		if (status != GL_FRAMEBUFFER_COMPLETE) {
-			printf("err status: %x\n", status);
-			_render_target_clear(rt);
-			ERR_FAIL_COND(status != GL_FRAMEBUFFER_COMPLETE);
-		}
+			glGenTextures(1, &rt->buffers.effect);
+			glBindTexture(GL_TEXTURE_2D, rt->buffers.effect);
+			glTexImage2D(GL_TEXTURE_2D, 0, color_internal_format, rt->width, rt->height, 0,
+					color_format, color_type, NULL);
+			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+			glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+			glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+			glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+					GL_TEXTURE_2D, rt->buffers.effect, 0);
 
 
-		glBindFramebuffer(GL_FRAMEBUFFER, RasterizerStorageGLES3::system_fbo);
+			if (status != GL_FRAMEBUFFER_COMPLETE) {
+				printf("err status: %x\n", status);
+				_render_target_clear(rt);
+				ERR_FAIL_COND(status != GL_FRAMEBUFFER_COMPLETE);
+			}
 
 
-		if (status != GL_FRAMEBUFFER_COMPLETE) {
-			_render_target_clear(rt);
-			ERR_FAIL_COND(status != GL_FRAMEBUFFER_COMPLETE);
+			glBindFramebuffer(GL_FRAMEBUFFER, RasterizerStorageGLES3::system_fbo);
+
+			if (status != GL_FRAMEBUFFER_COMPLETE) {
+				_render_target_clear(rt);
+				ERR_FAIL_COND(status != GL_FRAMEBUFFER_COMPLETE);
+			}
+
+			///////////////// ssao
+
+			//AO strength textures
+			for (int i = 0; i < 2; i++) {
+
+				glGenFramebuffers(1, &rt->effects.ssao.blur_fbo[i]);
+				glBindFramebuffer(GL_FRAMEBUFFER, rt->effects.ssao.blur_fbo[i]);
+				glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
+						GL_TEXTURE_2D, rt->depth, 0);
+
+				glGenTextures(1, &rt->effects.ssao.blur_red[i]);
+				glBindTexture(GL_TEXTURE_2D, rt->effects.ssao.blur_red[i]);
+
+				glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, rt->width, rt->height, 0, GL_RED, GL_UNSIGNED_BYTE, NULL);
+				glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+				glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+				glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+				glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+
+				glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt->effects.ssao.blur_red[i], 0);
+
+				status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+				if (status != GL_FRAMEBUFFER_COMPLETE) {
+					_render_target_clear(rt);
+					ERR_FAIL_COND(status != GL_FRAMEBUFFER_COMPLETE);
+				}
+			}
+			//5 mip levels for depth texture, but base is read separately
+
+			glGenTextures(1, &rt->effects.ssao.linear_depth);
+			glBindTexture(GL_TEXTURE_2D, rt->effects.ssao.linear_depth);
+
+			int ssao_w = rt->width / 2;
+			int ssao_h = rt->height / 2;
+
+			for (int i = 0; i < 4; i++) { //5, but 4 mips, base is read directly to save bw
+
+				glTexImage2D(GL_TEXTURE_2D, i, GL_R16UI, ssao_w, ssao_h, 0, GL_RED_INTEGER, GL_UNSIGNED_SHORT, NULL);
+				ssao_w >>= 1;
+				ssao_h >>= 1;
+			}
+
+			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
+			glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+			glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
+			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 3);
+
+			for (int i = 0; i < 4; i++) { //5, but 4 mips, base is read directly to save bw
+
+				GLuint fbo;
+				glGenFramebuffers(1, &fbo);
+				glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+				glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt->effects.ssao.linear_depth, i);
+				rt->effects.ssao.depth_mipmap_fbos.push_back(fbo);
+			}
+
+			//////Exposure
+
+			glGenFramebuffers(1, &rt->exposure.fbo);
+			glBindFramebuffer(GL_FRAMEBUFFER, rt->exposure.fbo);
+
+			glGenTextures(1, &rt->exposure.color);
+			glBindTexture(GL_TEXTURE_2D, rt->exposure.color);
+			glTexImage2D(GL_TEXTURE_2D, 0, GL_R32F, 1, 1, 0, GL_RED, GL_FLOAT, NULL);
+			glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt->exposure.color, 0);
+
+			status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+			if (status != GL_FRAMEBUFFER_COMPLETE) {
+				_render_target_clear(rt);
+				ERR_FAIL_COND(status != GL_FRAMEBUFFER_COMPLETE);
+			}
 		}
 		}
+	}
+
+	if (!rt->flags[RENDER_TARGET_NO_SAMPLING]) {
 
 
 		for (int i = 0; i < 2; i++) {
 		for (int i = 0; i < 2; i++) {
 
 
@@ -5738,7 +5818,7 @@ void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt) {
 				glBindFramebuffer(GL_FRAMEBUFFER, mm.fbo);
 				glBindFramebuffer(GL_FRAMEBUFFER, mm.fbo);
 				glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt->effects.mip_maps[i].color, j);
 				glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt->effects.mip_maps[i].color, j);
 
 
-				status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+				GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
 				if (status != GL_FRAMEBUFFER_COMPLETE) {
 				if (status != GL_FRAMEBUFFER_COMPLETE) {
 					_render_target_clear(rt);
 					_render_target_clear(rt);
 					ERR_FAIL_COND(status != GL_FRAMEBUFFER_COMPLETE);
 					ERR_FAIL_COND(status != GL_FRAMEBUFFER_COMPLETE);
@@ -5758,79 +5838,6 @@ void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt) {
 			glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
 			glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
 			glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
 			glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
 		}
 		}
-		///////////////// ssao
-
-		//AO strength textures
-		for (int i = 0; i < 2; i++) {
-
-			glGenFramebuffers(1, &rt->effects.ssao.blur_fbo[i]);
-			glBindFramebuffer(GL_FRAMEBUFFER, rt->effects.ssao.blur_fbo[i]);
-			glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
-					GL_TEXTURE_2D, rt->depth, 0);
-
-			glGenTextures(1, &rt->effects.ssao.blur_red[i]);
-			glBindTexture(GL_TEXTURE_2D, rt->effects.ssao.blur_red[i]);
-
-			glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, rt->width, rt->height, 0, GL_RED, GL_UNSIGNED_BYTE, NULL);
-			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-			glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
-			glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-
-			glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt->effects.ssao.blur_red[i], 0);
-
-			status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
-			if (status != GL_FRAMEBUFFER_COMPLETE) {
-				_render_target_clear(rt);
-				ERR_FAIL_COND(status != GL_FRAMEBUFFER_COMPLETE);
-			}
-		}
-		//5 mip levels for depth texture, but base is read separately
-
-		glGenTextures(1, &rt->effects.ssao.linear_depth);
-		glBindTexture(GL_TEXTURE_2D, rt->effects.ssao.linear_depth);
-
-		int ssao_w = rt->width / 2;
-		int ssao_h = rt->height / 2;
-
-		for (int i = 0; i < 4; i++) { //5, but 4 mips, base is read directly to save bw
-
-			glTexImage2D(GL_TEXTURE_2D, i, GL_R16UI, ssao_w, ssao_h, 0, GL_RED_INTEGER, GL_UNSIGNED_SHORT, NULL);
-			ssao_w >>= 1;
-			ssao_h >>= 1;
-		}
-
-		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
-		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
-		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
-		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 3);
-
-		for (int i = 0; i < 4; i++) { //5, but 4 mips, base is read directly to save bw
-
-			GLuint fbo;
-			glGenFramebuffers(1, &fbo);
-			glBindFramebuffer(GL_FRAMEBUFFER, fbo);
-			glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt->effects.ssao.linear_depth, i);
-			rt->effects.ssao.depth_mipmap_fbos.push_back(fbo);
-		}
-
-		//////Exposure
-
-		glGenFramebuffers(1, &rt->exposure.fbo);
-		glBindFramebuffer(GL_FRAMEBUFFER, rt->exposure.fbo);
-
-		glGenTextures(1, &rt->exposure.color);
-		glBindTexture(GL_TEXTURE_2D, rt->exposure.color);
-		glTexImage2D(GL_TEXTURE_2D, 0, GL_R32F, 1, 1, 0, GL_RED, GL_FLOAT, NULL);
-		glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt->exposure.color, 0);
-
-		status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
-		if (status != GL_FRAMEBUFFER_COMPLETE) {
-			_render_target_clear(rt);
-			ERR_FAIL_COND(status != GL_FRAMEBUFFER_COMPLETE);
-		}
 	}
 	}
 }
 }
 
 
@@ -5855,9 +5862,10 @@ RID RasterizerStorageGLES3::render_target_create() {
 	t->srgb = false;
 	t->srgb = false;
 	t->total_data_size = 0;
 	t->total_data_size = 0;
 	t->ignore_mipmaps = false;
 	t->ignore_mipmaps = false;
-	t->mipmaps = 0;
+	t->mipmaps = 1;
 	t->active = true;
 	t->active = true;
 	t->tex_id = 0;
 	t->tex_id = 0;
+	t->render_target = rt;
 
 
 	rt->texture = texture_owner.make_rid(t);
 	rt->texture = texture_owner.make_rid(t);
 
 
@@ -5894,8 +5902,10 @@ void RasterizerStorageGLES3::render_target_set_flag(RID p_render_target, RenderT
 	rt->flags[p_flag] = p_value;
 	rt->flags[p_flag] = p_value;
 
 
 	switch (p_flag) {
 	switch (p_flag) {
+		case RENDER_TARGET_HDR:
 		case RENDER_TARGET_NO_3D:
 		case RENDER_TARGET_NO_3D:
-		case RENDER_TARGET_TRANSPARENT: {
+		case RENDER_TARGET_NO_SAMPLING:
+		case RENDER_TARGET_NO_3D_EFFECTS: {
 			//must reset for these formats
 			//must reset for these formats
 			_render_target_clear(rt);
 			_render_target_clear(rt);
 			_render_target_allocate(rt);
 			_render_target_allocate(rt);
@@ -6337,9 +6347,6 @@ bool RasterizerStorageGLES3::has_os_feature(const String &p_feature) const {
 
 
 void RasterizerStorageGLES3::initialize() {
 void RasterizerStorageGLES3::initialize() {
 
 
-	config.render_arch = RENDER_ARCH_DESKTOP;
-	//config.fbo_deferred=int(Globals::get_singleton()->get("rendering/gles3/lighting_technique"));
-
 	RasterizerStorageGLES3::system_fbo = 0;
 	RasterizerStorageGLES3::system_fbo = 0;
 
 
 	//// extensions config
 	//// extensions config

+ 2 - 3
drivers/gles3/rasterizer_storage_gles3.h

@@ -61,8 +61,6 @@ public:
 
 
 	struct Config {
 	struct Config {
 
 
-		RenderArchitecture render_arch;
-
 		bool shrink_textures_x2;
 		bool shrink_textures_x2;
 		bool use_fast_texture_filter;
 		bool use_fast_texture_filter;
 		bool use_anisotropic_filter;
 		bool use_anisotropic_filter;
@@ -1209,9 +1207,10 @@ public:
 
 
 			flags[RENDER_TARGET_VFLIP] = false;
 			flags[RENDER_TARGET_VFLIP] = false;
 			flags[RENDER_TARGET_TRANSPARENT] = false;
 			flags[RENDER_TARGET_TRANSPARENT] = false;
+			flags[RENDER_TARGET_NO_3D_EFFECTS] = false;
 			flags[RENDER_TARGET_NO_3D] = false;
 			flags[RENDER_TARGET_NO_3D] = false;
-			flags[RENDER_TARGET_HDR] = true;
 			flags[RENDER_TARGET_NO_SAMPLING] = false;
 			flags[RENDER_TARGET_NO_SAMPLING] = false;
+			flags[RENDER_TARGET_HDR] = true;
 
 
 			last_exposure_tick = 0;
 			last_exposure_tick = 0;
 		}
 		}

+ 4 - 0
drivers/gles3/shaders/copy.glsl

@@ -23,6 +23,10 @@ void main() {
 	cube_interp = cube_in;
 	cube_interp = cube_in;
 #else
 #else
 	uv_interp = uv_in;
 	uv_interp = uv_in;
+#ifdef V_FLIP
+	uv_interp.y = 1.0-uv_interp.y;
+#endif
+
 #endif
 #endif
 	uv2_interp = uv2_in;
 	uv2_interp = uv2_in;
 	gl_Position = vertex_attrib;
 	gl_Position = vertex_attrib;

+ 1 - 1
drivers/gles3/shaders/scene.glsl

@@ -1709,7 +1709,7 @@ FRAGMENT_SHADER_CODE
 	sss_buffer = sss_strength;
 	sss_buffer = sss_strength;
 #endif
 #endif
 
 
-#else
+#else //USE_MULTIPLE_RENDER_TARGETS
 
 
 
 
 #ifdef SHADELESS
 #ifdef SHADELESS

+ 3 - 2
drivers/gles3/shaders/tonemap.glsl

@@ -6,12 +6,13 @@ layout(location=4) in vec2 uv_in;
 
 
 out vec2 uv_interp;
 out vec2 uv_interp;
 
 
-
-
 void main() {
 void main() {
 
 
 	gl_Position = vertex_attrib;
 	gl_Position = vertex_attrib;
 	uv_interp = uv_in;
 	uv_interp = uv_in;
+#ifdef V_FLIP
+	uv_interp.y = 1.0-uv_interp.y;
+#endif
 
 
 }
 }
 
 

+ 0 - 35
drivers/png/resource_saver_png.cpp

@@ -55,41 +55,6 @@ Error ResourceSaverPNG::save(const String &p_path, const RES &p_resource, uint32
 	Error err = save_image(p_path, img);
 	Error err = save_image(p_path, img);
 
 
 	if (err == OK) {
 	if (err == OK) {
-
-		bool global_filter = GlobalConfig::get_singleton()->get("image_loader/filter");
-		bool global_mipmaps = GlobalConfig::get_singleton()->get("image_loader/gen_mipmaps");
-		bool global_repeat = GlobalConfig::get_singleton()->get("image_loader/repeat");
-
-		String text;
-
-		if (global_filter != bool(texture->get_flags() & Texture::FLAG_FILTER)) {
-			text += bool(texture->get_flags() & Texture::FLAG_FILTER) ? "filter=true\n" : "filter=false\n";
-		}
-		if (global_mipmaps != bool(texture->get_flags() & Texture::FLAG_MIPMAPS)) {
-			text += bool(texture->get_flags() & Texture::FLAG_MIPMAPS) ? "gen_mipmaps=true\n" : "gen_mipmaps=false\n";
-		}
-		if (global_repeat != bool(texture->get_flags() & Texture::FLAG_REPEAT)) {
-			text += bool(texture->get_flags() & Texture::FLAG_REPEAT) ? "repeat=true\n" : "repeat=false\n";
-		}
-		if (bool(texture->get_flags() & Texture::FLAG_ANISOTROPIC_FILTER)) {
-			text += "anisotropic=true\n";
-		}
-		if (bool(texture->get_flags() & Texture::FLAG_CONVERT_TO_LINEAR)) {
-			text += "tolinear=true\n";
-		}
-		if (bool(texture->get_flags() & Texture::FLAG_MIRRORED_REPEAT)) {
-			text += "mirroredrepeat=true\n";
-		}
-
-		if (text != "" || FileAccess::exists(p_path + ".flags")) {
-
-			FileAccess *f = FileAccess::open(p_path + ".flags", FileAccess::WRITE);
-			if (f) {
-
-				f->store_string(text);
-				memdelete(f);
-			}
-		}
 	}
 	}
 
 
 	return err;
 	return err;

+ 42 - 45
editor/editor_node.cpp

@@ -823,56 +823,54 @@ void EditorNode::_save_scene_with_preview(String p_file) {
 	}
 	}
 	save.step(TTR("Creating Thumbnail"), 1);
 	save.step(TTR("Creating Thumbnail"), 1);
 	//current view?
 	//current view?
-	int screen = -1;
-	for (int i = 0; i < editor_table.size(); i++) {
-		if (editor_plugin_screen == editor_table[i]) {
-			screen = i;
-			break;
-		}
+
+	Ref<Image> img;
+	if (is2d) {
+		img = scene_root->get_texture()->get_data();
+	} else {
+		img = SpatialEditor::get_singleton()->get_editor_viewport(0)->get_viewport_node()->get_texture()->get_data();
 	}
 	}
 
 
-	_editor_select(is2d ? EDITOR_2D : EDITOR_3D);
+	if (img.is_valid()) {
+		save.step(TTR("Creating Thumbnail"), 2);
+		save.step(TTR("Creating Thumbnail"), 3);
 
 
-	save.step(TTR("Creating Thumbnail"), 2);
-	save.step(TTR("Creating Thumbnail"), 3);
-#if 0
-	Image img = VS::get_singleton()->viewport_texture(scree_capture(viewport);
-	int preview_size = EditorSettings::get_singleton()->get("filesystem/file_dialog/thumbnail_size");
-	preview_size*=EDSCALE;
-	int width,height;
-	if (img.get_width() > preview_size && img.get_width() >= img.get_height()) {
+		int preview_size = EditorSettings::get_singleton()->get("filesystem/file_dialog/thumbnail_size");
+		preview_size *= EDSCALE;
+		int width, height;
+		if (img->get_width() > preview_size && img->get_width() >= img->get_height()) {
 
 
-		width=preview_size;
-		height = img.get_height() * preview_size / img.get_width();
-	} else if (img.get_height() > preview_size &&  img.get_height() >= img.get_width()) {
+			width = preview_size;
+			height = img->get_height() * preview_size / img->get_width();
+		} else if (img->get_height() > preview_size && img->get_height() >= img->get_width()) {
 
 
-		height=preview_size;
-		width = img.get_width() * preview_size / img.get_height();
-	}  else {
+			height = preview_size;
+			width = img->get_width() * preview_size / img->get_height();
+		} else {
 
 
-		width=img.get_width();
-		height=img.get_height();
-	}
+			width = img->get_width();
+			height = img->get_height();
+		}
 
 
-	img.convert(Image::FORMAT_RGB8);
-	img.resize(width,height);
+		img->convert(Image::FORMAT_RGB8);
+		img->resize(width, height);
+		img->flip_y();
 
 
-	String pfile = EditorSettings::get_singleton()->get_settings_path().plus_file("tmp/last_scene_preview.png");
-	img.save_png(pfile);
-	Vector<uint8_t> imgdata = FileAccess::get_file_as_array(pfile);
+		//save thumbnail directly, as thumbnailer may not update due to actual scene not changing md5
+		String temp_path = EditorSettings::get_singleton()->get_settings_path().plus_file("tmp");
+		String cache_base = GlobalConfig::get_singleton()->globalize_path(p_file).md5_text();
+		cache_base = temp_path.plus_file("resthumb-" + cache_base);
 
 
-	//print_line("img data is "+itos(imgdata.size()));
+		//does not have it, try to load a cached thumbnail
 
 
-	if (editor_data.get_edited_scene_import_metadata().is_null())
-		editor_data.set_edited_scene_import_metadata(Ref<ResourceImportMetadata>( memnew( ResourceImportMetadata ) ) );
-	editor_data.get_edited_scene_import_metadata()->set_option("thumbnail",imgdata);
-#endif
-	//tamanio tel thumbnail
-	if (screen != -1) {
-		_editor_select(screen);
+		String file = cache_base + ".png";
+
+		img->save_png(file);
 	}
 	}
+
 	save.step(TTR("Saving Scene"), 4);
 	save.step(TTR("Saving Scene"), 4);
 	_save_scene(p_file);
 	_save_scene(p_file);
+	EditorResourcePreview::get_singleton()->check_for_invalidation(p_file);
 }
 }
 
 
 void EditorNode::_save_scene(String p_file, int idx) {
 void EditorNode::_save_scene(String p_file, int idx) {
@@ -6057,14 +6055,13 @@ EditorNode::EditorNode() {
 		plugin_init_callbacks[i]();
 		plugin_init_callbacks[i]();
 	}
 	}
 
 
-	/*resource_preview->add_preview_generator( Ref<EditorTexturePreviewPlugin>( memnew(EditorTexturePreviewPlugin )));
-	resource_preview->add_preview_generator( Ref<EditorPackedScenePreviewPlugin>( memnew(EditorPackedScenePreviewPlugin )));
-	resource_preview->add_preview_generator( Ref<EditorMaterialPreviewPlugin>( memnew(EditorMaterialPreviewPlugin )));
-	resource_preview->add_preview_generator( Ref<EditorScriptPreviewPlugin>( memnew(EditorScriptPreviewPlugin )));
-	resource_preview->add_preview_generator( Ref<EditorSamplePreviewPlugin>( memnew(EditorSamplePreviewPlugin )));
-	resource_preview->add_preview_generator( Ref<EditorMeshPreviewPlugin>( memnew(EditorMeshPreviewPlugin )));
-	resource_preview->add_preview_generator( Ref<EditorBitmapPreviewPlugin>( memnew(EditorBitmapPreviewPlugin )));
-*/
+	resource_preview->add_preview_generator(Ref<EditorTexturePreviewPlugin>(memnew(EditorTexturePreviewPlugin)));
+	resource_preview->add_preview_generator(Ref<EditorPackedScenePreviewPlugin>(memnew(EditorPackedScenePreviewPlugin)));
+	resource_preview->add_preview_generator(Ref<EditorMaterialPreviewPlugin>(memnew(EditorMaterialPreviewPlugin)));
+	resource_preview->add_preview_generator(Ref<EditorScriptPreviewPlugin>(memnew(EditorScriptPreviewPlugin)));
+	//resource_preview->add_preview_generator( Ref<EditorSamplePreviewPlugin>( memnew(EditorSamplePreviewPlugin )));
+	resource_preview->add_preview_generator(Ref<EditorMeshPreviewPlugin>(memnew(EditorMeshPreviewPlugin)));
+	resource_preview->add_preview_generator(Ref<EditorBitmapPreviewPlugin>(memnew(EditorBitmapPreviewPlugin)));
 
 
 	circle_step_msec = OS::get_singleton()->get_ticks_msec();
 	circle_step_msec = OS::get_singleton()->get_ticks_msec();
 	circle_step_frame = Engine::get_singleton()->get_frames_drawn();
 	circle_step_frame = Engine::get_singleton()->get_frames_drawn();

+ 12 - 4
editor/editor_resource_preview.cpp

@@ -190,7 +190,7 @@ void EditorResourcePreview::_thread() {
 			} else {
 			} else {
 				preview_mutex->unlock();
 				preview_mutex->unlock();
 
 
-				Ref<Texture> texture;
+				Ref<ImageTexture> texture;
 
 
 				//print_line("pop from queue "+item.path);
 				//print_line("pop from queue "+item.path);
 
 
@@ -229,6 +229,7 @@ void EditorResourcePreview::_thread() {
 						bool cache_valid = true;
 						bool cache_valid = true;
 
 
 						if (tsize != thumbnail_size) {
 						if (tsize != thumbnail_size) {
+
 							cache_valid = false;
 							cache_valid = false;
 							memdelete(f);
 							memdelete(f);
 						} else if (last_modtime != modtime) {
 						} else if (last_modtime != modtime) {
@@ -240,6 +241,7 @@ void EditorResourcePreview::_thread() {
 							if (last_md5 != md5) {
 							if (last_md5 != md5) {
 
 
 								cache_valid = false;
 								cache_valid = false;
+
 							} else {
 							} else {
 								//update modified time
 								//update modified time
 
 
@@ -252,14 +254,20 @@ void EditorResourcePreview::_thread() {
 							memdelete(f);
 							memdelete(f);
 						}
 						}
 
 
-						cache_valid = false;
+						//cache_valid = false;
 
 
 						if (cache_valid) {
 						if (cache_valid) {
 
 
-							texture = ResourceLoader::load(cache_base + ".png", "ImageTexture", true);
-							if (!texture.is_valid()) {
+							Ref<Image> img;
+							img.instance();
+
+							if (img->load(cache_base + ".png") != OK) {
 								//well fuck
 								//well fuck
 								cache_valid = false;
 								cache_valid = false;
+							} else {
+
+								texture.instance();
+								texture->create_from_image(img, Texture::FLAG_FILTER);
 							}
 							}
 						}
 						}
 
 

+ 1 - 1
editor/import/resource_importer_obj.cpp

@@ -54,7 +54,7 @@ String ResourceImporterOBJ::get_save_extension() const {
 
 
 String ResourceImporterOBJ::get_resource_type() const {
 String ResourceImporterOBJ::get_resource_type() const {
 
 
-	return "Mesh";
+	return "ArrayMesh";
 }
 }
 
 
 bool ResourceImporterOBJ::get_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const {
 bool ResourceImporterOBJ::get_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const {

+ 260 - 283
editor/plugins/editor_preview_plugins.cpp

@@ -39,239 +39,226 @@
 #include "scene/resources/bit_mask.h"
 #include "scene/resources/bit_mask.h"
 #include "scene/resources/mesh.h"
 #include "scene/resources/mesh.h"
 
 
-#if 0
-bool EditorTexturePreviewPlugin::handles(const String& p_type) const {
+bool EditorTexturePreviewPlugin::handles(const String &p_type) const {
 
 
-	return (ClassDB::is_type(p_type,"ImageTexture") || ClassDB::is_type(p_type, "AtlasTexture"));
+	return ClassDB::is_parent_class(p_type, "Texture");
 }
 }
 
 
-Ref<Texture> EditorTexturePreviewPlugin::generate(const RES& p_from) {
+Ref<Texture> EditorTexturePreviewPlugin::generate(const RES &p_from) {
 
 
-	Image img;
+	Ref<Image> img;
 	Ref<AtlasTexture> atex = p_from;
 	Ref<AtlasTexture> atex = p_from;
 	if (atex.is_valid()) {
 	if (atex.is_valid()) {
-		Ref<ImageTexture> tex = atex->get_atlas();
+		Ref<Texture> tex = atex->get_atlas();
 		if (!tex.is_valid()) {
 		if (!tex.is_valid()) {
 			return Ref<Texture>();
 			return Ref<Texture>();
 		}
 		}
-		Image atlas = tex->get_data();
-		img = atlas.get_rect(atex->get_region());
-	}
-	else {
-		Ref<ImageTexture> tex = p_from;
+		Ref<Image> atlas = tex->get_data();
+		img = atlas->get_rect(atex->get_region());
+	} else {
+		Ref<Texture> tex = p_from;
 		img = tex->get_data();
 		img = tex->get_data();
 	}
 	}
 
 
-	if (img.empty())
+	if (img.is_null() || img->empty())
 		return Ref<Texture>();
 		return Ref<Texture>();
 
 
-	img.clear_mipmaps();
+	img->clear_mipmaps();
 
 
 	int thumbnail_size = EditorSettings::get_singleton()->get("filesystem/file_dialog/thumbnail_size");
 	int thumbnail_size = EditorSettings::get_singleton()->get("filesystem/file_dialog/thumbnail_size");
-	thumbnail_size*=EDSCALE;
-	if (img.is_compressed()) {
-		if (img.decompress()!=OK)
+	thumbnail_size *= EDSCALE;
+	if (img->is_compressed()) {
+		if (img->decompress() != OK)
 			return Ref<Texture>();
 			return Ref<Texture>();
-    } else if (img.get_format()!=Image::FORMAT_RGB8 && img.get_format()!=Image::FORMAT_RGBA8) {
-		img.convert(Image::FORMAT_RGBA8);
+	} else if (img->get_format() != Image::FORMAT_RGB8 && img->get_format() != Image::FORMAT_RGBA8) {
+		img->convert(Image::FORMAT_RGBA8);
 	}
 	}
 
 
-	int width,height;
-	if (img.get_width() > thumbnail_size && img.get_width() >= img.get_height()) {
+	int width, height;
+	if (img->get_width() > thumbnail_size && img->get_width() >= img->get_height()) {
 
 
-		width=thumbnail_size;
-		height = img.get_height() * thumbnail_size / img.get_width();
-	} else if (img.get_height() > thumbnail_size &&  img.get_height() >= img.get_width()) {
+		width = thumbnail_size;
+		height = img->get_height() * thumbnail_size / img->get_width();
+	} else if (img->get_height() > thumbnail_size && img->get_height() >= img->get_width()) {
 
 
-		height=thumbnail_size;
-		width = img.get_width() * thumbnail_size / img.get_height();
-	}  else {
+		height = thumbnail_size;
+		width = img->get_width() * thumbnail_size / img->get_height();
+	} else {
 
 
-		width=img.get_width();
-		height=img.get_height();
+		width = img->get_width();
+		height = img->get_height();
 	}
 	}
 
 
-	img.resize(width,height);
+	img->resize(width, height);
 
 
-	Ref<ImageTexture> ptex = Ref<ImageTexture>( memnew( ImageTexture ));
+	Ref<ImageTexture> ptex = Ref<ImageTexture>(memnew(ImageTexture));
 
 
-	ptex->create_from_image(img,0);
+	ptex->create_from_image(img, 0);
 	return ptex;
 	return ptex;
-
 }
 }
 
 
 EditorTexturePreviewPlugin::EditorTexturePreviewPlugin() {
 EditorTexturePreviewPlugin::EditorTexturePreviewPlugin() {
-
-
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////////////
 
 
-bool EditorBitmapPreviewPlugin::handles(const String& p_type) const {
+bool EditorBitmapPreviewPlugin::handles(const String &p_type) const {
 
 
-	return ClassDB::is_type(p_type,"BitMap");
+	return ClassDB::is_parent_class(p_type, "BitMap");
 }
 }
 
 
-Ref<Texture> EditorBitmapPreviewPlugin::generate(const RES& p_from) {
+Ref<Texture> EditorBitmapPreviewPlugin::generate(const RES &p_from) {
 
 
-	Ref<BitMap> bm =p_from;
+	Ref<BitMap> bm = p_from;
 
 
-	if (bm->get_size()==Size2()) {
+	if (bm->get_size() == Size2()) {
 		return Ref<Texture>();
 		return Ref<Texture>();
 	}
 	}
 
 
 	PoolVector<uint8_t> data;
 	PoolVector<uint8_t> data;
 
 
-	data.resize(bm->get_size().width*bm->get_size().height);
+	data.resize(bm->get_size().width * bm->get_size().height);
 
 
 	{
 	{
-		PoolVector<uint8_t>::Write w=data.write();
+		PoolVector<uint8_t>::Write w = data.write();
 
 
-		for(int i=0;i<bm->get_size().width;i++) {
-			for(int j=0;j<bm->get_size().height;j++) {
-				if (bm->get_bit(Point2i(i,j))) {
-					w[j*bm->get_size().width+i]=255;
+		for (int i = 0; i < bm->get_size().width; i++) {
+			for (int j = 0; j < bm->get_size().height; j++) {
+				if (bm->get_bit(Point2i(i, j))) {
+					w[j * bm->get_size().width + i] = 255;
 				} else {
 				} else {
-					w[j*bm->get_size().width+i]=0;
-
+					w[j * bm->get_size().width + i] = 0;
 				}
 				}
 			}
 			}
-
 		}
 		}
 	}
 	}
 
 
-
-	Image img(bm->get_size().width,bm->get_size().height,0,Image::FORMAT_L8,data);
+	Ref<Image> img;
+	img.instance();
+	img->create(bm->get_size().width, bm->get_size().height, 0, Image::FORMAT_L8, data);
 
 
 	int thumbnail_size = EditorSettings::get_singleton()->get("filesystem/file_dialog/thumbnail_size");
 	int thumbnail_size = EditorSettings::get_singleton()->get("filesystem/file_dialog/thumbnail_size");
-	thumbnail_size*=EDSCALE;
-	if (img.is_compressed()) {
-		if (img.decompress()!=OK)
+	thumbnail_size *= EDSCALE;
+	if (img->is_compressed()) {
+		if (img->decompress() != OK)
 			return Ref<Texture>();
 			return Ref<Texture>();
-	} else if (img.get_format()!=Image::FORMAT_RGB8 && img.get_format()!=Image::FORMAT_RGBA8) {
-		img.convert(Image::FORMAT_RGBA8);
+	} else if (img->get_format() != Image::FORMAT_RGB8 && img->get_format() != Image::FORMAT_RGBA8) {
+		img->convert(Image::FORMAT_RGBA8);
 	}
 	}
 
 
-	int width,height;
-	if (img.get_width() > thumbnail_size && img.get_width() >= img.get_height()) {
+	int width, height;
+	if (img->get_width() > thumbnail_size && img->get_width() >= img->get_height()) {
 
 
-		width=thumbnail_size;
-		height = img.get_height() * thumbnail_size / img.get_width();
-	} else if (img.get_height() > thumbnail_size &&  img.get_height() >= img.get_width()) {
+		width = thumbnail_size;
+		height = img->get_height() * thumbnail_size / img->get_width();
+	} else if (img->get_height() > thumbnail_size && img->get_height() >= img->get_width()) {
 
 
-		height=thumbnail_size;
-		width = img.get_width() * thumbnail_size / img.get_height();
-	}  else {
+		height = thumbnail_size;
+		width = img->get_width() * thumbnail_size / img->get_height();
+	} else {
 
 
-		width=img.get_width();
-		height=img.get_height();
+		width = img->get_width();
+		height = img->get_height();
 	}
 	}
 
 
-	img.resize(width,height);
+	img->resize(width, height);
 
 
-	Ref<ImageTexture> ptex = Ref<ImageTexture>( memnew( ImageTexture ));
+	Ref<ImageTexture> ptex = Ref<ImageTexture>(memnew(ImageTexture));
 
 
-	ptex->create_from_image(img,0);
+	ptex->create_from_image(img, 0);
 	return ptex;
 	return ptex;
-
 }
 }
 
 
 EditorBitmapPreviewPlugin::EditorBitmapPreviewPlugin() {
 EditorBitmapPreviewPlugin::EditorBitmapPreviewPlugin() {
-
-
 }
 }
 
 
 ///////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////
 
 
+bool EditorPackedScenePreviewPlugin::handles(const String &p_type) const {
 
 
-Ref<Texture> EditorPackedScenePreviewPlugin::_gen_from_imd(Ref<ResourceImportMetadata> p_imd) {
-
-	if (p_imd.is_null()) {
-		return Ref<Texture>();
-	}
+	return ClassDB::is_parent_class(p_type, "PackedScene");
+}
+Ref<Texture> EditorPackedScenePreviewPlugin::generate(const RES &p_from) {
 
 
-	if (!p_imd->has_option("thumbnail"))
-		return Ref<Texture>();
+	return generate_from_path(p_from->get_path());
+}
 
 
-	Variant tn = p_imd->get_option("thumbnail");
-	//print_line(Variant::get_type_name(tn.get_type()));
-	PoolVector<uint8_t> thumbnail = tn;
+Ref<Texture> EditorPackedScenePreviewPlugin::generate_from_path(const String &p_path) {
 
 
-	int len = thumbnail.size();
-	if (len==0)
-		return Ref<Texture>();
+	String temp_path = EditorSettings::get_singleton()->get_settings_path().plus_file("tmp");
+	String cache_base = GlobalConfig::get_singleton()->globalize_path(p_path).md5_text();
+	cache_base = temp_path.plus_file("resthumb-" + cache_base);
 
 
+	//does not have it, try to load a cached thumbnail
 
 
-	PoolVector<uint8_t>::Read r = thumbnail.read();
+	String path = cache_base + ".png";
 
 
-	Image img(r.ptr(),len);
-	if (img.empty())
+	if (!FileAccess::exists(path))
 		return Ref<Texture>();
 		return Ref<Texture>();
 
 
-	Ref<ImageTexture> ptex = Ref<ImageTexture>( memnew( ImageTexture ));
-	ptex->create_from_image(img,0);
-	return ptex;
+	Ref<Image> img;
+	img.instance();
+	Error err = img->load(path);
+	if (err == OK) {
 
 
-}
+		Ref<ImageTexture> ptex = Ref<ImageTexture>(memnew(ImageTexture));
 
 
-bool EditorPackedScenePreviewPlugin::handles(const String& p_type) const {
+		ptex->create_from_image(img, 0);
+		return ptex;
 
 
-	return ClassDB::is_type(p_type,"PackedScene");
+	} else {
+		return Ref<Texture>();
+	}
 }
 }
-Ref<Texture> EditorPackedScenePreviewPlugin::generate(const RES& p_from) {
 
 
-	Ref<ResourceImportMetadata> imd = p_from->get_import_metadata();
-	return _gen_from_imd(imd);
+EditorPackedScenePreviewPlugin::EditorPackedScenePreviewPlugin() {
 }
 }
 
 
-Ref<Texture> EditorPackedScenePreviewPlugin::generate_from_path(const String& p_path) {
+//////////////////////////////////////////////////////////////////
+
+void EditorMaterialPreviewPlugin::_preview_done(const Variant &p_udata) {
 
 
-	Ref<ResourceImportMetadata> imd = ResourceLoader::load_import_metadata(p_path);
-	return _gen_from_imd(imd);
+	preview_done = true;
 }
 }
 
 
-EditorPackedScenePreviewPlugin::EditorPackedScenePreviewPlugin() {
+void EditorMaterialPreviewPlugin::_bind_methods() {
 
 
+	ClassDB::bind_method("_preview_done", &EditorMaterialPreviewPlugin::_preview_done);
 }
 }
 
 
-//////////////////////////////////////////////////////////////////
+bool EditorMaterialPreviewPlugin::handles(const String &p_type) const {
 
 
-bool EditorMaterialPreviewPlugin::handles(const String& p_type) const {
-
-	return ClassDB::is_type(p_type,"Material"); //any material
+	return ClassDB::is_parent_class(p_type, "Material"); //any material
 }
 }
 
 
-Ref<Texture> EditorMaterialPreviewPlugin::generate(const RES& p_from) {
+Ref<Texture> EditorMaterialPreviewPlugin::generate(const RES &p_from) {
 
 
 	Ref<Material> material = p_from;
 	Ref<Material> material = p_from;
-	ERR_FAIL_COND_V(material.is_null(),Ref<Texture>());
+	ERR_FAIL_COND_V(material.is_null(), Ref<Texture>());
 
 
-	VS::get_singleton()->mesh_surface_set_material(sphere,0,material->get_rid());
+	VS::get_singleton()->mesh_surface_set_material(sphere, 0, material->get_rid());
 
 
-	VS::get_singleton()->viewport_queue_screen_capture(viewport);
-	VS::get_singleton()->viewport_set_render_target_update_mode(viewport,VS::RENDER_TARGET_UPDATE_ONCE); //once used for capture
+	VS::get_singleton()->viewport_set_update_mode(viewport, VS::VIEWPORT_UPDATE_ONCE); //once used for capture
 	//print_line("queue capture!");
 	//print_line("queue capture!");
-	Image img;
 
 
-	int timeout=1000;
-	while(timeout) {
-		//print_line("try capture?");
+	preview_done = false;
+	VS::get_singleton()->request_frame_drawn_callback(this, "_preview_done", Variant());
+
+	while (!preview_done) {
 		OS::get_singleton()->delay_usec(10);
 		OS::get_singleton()->delay_usec(10);
-		img = VS::get_singleton()->viewport_get_screen_capture(viewport);
-		if (!img.empty())
-			break;
-		timeout--;
 	}
 	}
 
 
-	//print_line("captured!");
-	VS::get_singleton()->mesh_surface_set_material(sphere,0,RID());
+	Ref<Image> img = VS::get_singleton()->VS::get_singleton()->texture_get_data(viewport_texture);
+	VS::get_singleton()->mesh_surface_set_material(sphere, 0, RID());
 
 
-	int thumbnail_size = EditorSettings::get_singleton()->get("filesystem/file_dialog/thumbnail_size");
-	thumbnail_size*=EDSCALE;
-	img.resize(thumbnail_size,thumbnail_size);
+	ERR_FAIL_COND_V(!img.is_valid(), Ref<ImageTexture>());
 
 
-	Ref<ImageTexture> ptex = Ref<ImageTexture>( memnew( ImageTexture ));
-	ptex->create_from_image(img,0);
+	int thumbnail_size = EditorSettings::get_singleton()->get("filesystem/file_dialog/thumbnail_size");
+	thumbnail_size *= EDSCALE;
+	img->convert(Image::FORMAT_RGBA8);
+	img->resize(thumbnail_size, thumbnail_size);
+	Ref<ImageTexture> ptex = Ref<ImageTexture>(memnew(ImageTexture));
+	ptex->create_from_image(img, 0);
 	return ptex;
 	return ptex;
 }
 }
 
 
@@ -280,70 +267,68 @@ EditorMaterialPreviewPlugin::EditorMaterialPreviewPlugin() {
 	scenario = VS::get_singleton()->scenario_create();
 	scenario = VS::get_singleton()->scenario_create();
 
 
 	viewport = VS::get_singleton()->viewport_create();
 	viewport = VS::get_singleton()->viewport_create();
-	VS::get_singleton()->viewport_set_as_render_target(viewport,true);
-	VS::get_singleton()->viewport_set_render_target_update_mode(viewport,VS::RENDER_TARGET_UPDATE_DISABLED);
-	VS::get_singleton()->viewport_set_scenario(viewport,scenario);
-	VS::ViewportRect vr;
-	vr.x=0;
-	vr.y=0;
-	vr.width=128;
-	vr.height=128;
-	VS::get_singleton()->viewport_set_rect(viewport,vr);
+	VS::get_singleton()->viewport_set_update_mode(viewport, VS::VIEWPORT_UPDATE_DISABLED);
+	VS::get_singleton()->viewport_set_scenario(viewport, scenario);
+	VS::get_singleton()->viewport_set_size(viewport, 128, 128);
+	VS::get_singleton()->viewport_set_transparent_background(viewport, true);
+	VS::get_singleton()->viewport_set_active(viewport, true);
+	VS::get_singleton()->viewport_set_vflip(viewport, true);
+	viewport_texture = VS::get_singleton()->viewport_get_texture(viewport);
 
 
 	camera = VS::get_singleton()->camera_create();
 	camera = VS::get_singleton()->camera_create();
-	VS::get_singleton()->viewport_attach_camera(viewport,camera);
-	VS::get_singleton()->camera_set_transform(camera,Transform(Matrix3(),Vector3(0,0,3)));
-	VS::get_singleton()->camera_set_perspective(camera,45,0.1,10);
+	VS::get_singleton()->viewport_attach_camera(viewport, camera);
+	VS::get_singleton()->camera_set_transform(camera, Transform(Basis(), Vector3(0, 0, 3)));
+	VS::get_singleton()->camera_set_perspective(camera, 45, 0.1, 10);
 
 
 	light = VS::get_singleton()->light_create(VS::LIGHT_DIRECTIONAL);
 	light = VS::get_singleton()->light_create(VS::LIGHT_DIRECTIONAL);
-	light_instance = VS::get_singleton()->instance_create2(light,scenario);
-	VS::get_singleton()->instance_set_transform(light_instance,Transform().looking_at(Vector3(-1,-1,-1),Vector3(0,1,0)));
+	light_instance = VS::get_singleton()->instance_create2(light, scenario);
+	VS::get_singleton()->instance_set_transform(light_instance, Transform().looking_at(Vector3(-1, -1, -1), Vector3(0, 1, 0)));
 
 
 	light2 = VS::get_singleton()->light_create(VS::LIGHT_DIRECTIONAL);
 	light2 = VS::get_singleton()->light_create(VS::LIGHT_DIRECTIONAL);
-	VS::get_singleton()->light_set_color(light2,VS::LIGHT_COLOR_DIFFUSE,Color(0.7,0.7,0.7));
-	VS::get_singleton()->light_set_color(light2,VS::LIGHT_COLOR_SPECULAR,Color(0.0,0.0,0.0));
-	light_instance2 = VS::get_singleton()->instance_create2(light2,scenario);
+	VS::get_singleton()->light_set_color(light2, Color(0.7, 0.7, 0.7));
+	//VS::get_singleton()->light_set_color(light2, Color(0.7, 0.7, 0.7));
+
+	light_instance2 = VS::get_singleton()->instance_create2(light2, scenario);
 
 
-	VS::get_singleton()->instance_set_transform(light_instance2,Transform().looking_at(Vector3(0,1,0),Vector3(0,0,1)));
+	VS::get_singleton()->instance_set_transform(light_instance2, Transform().looking_at(Vector3(0, 1, 0), Vector3(0, 0, 1)));
 
 
 	sphere = VS::get_singleton()->mesh_create();
 	sphere = VS::get_singleton()->mesh_create();
-	sphere_instance = VS::get_singleton()->instance_create2(sphere,scenario);
+	sphere_instance = VS::get_singleton()->instance_create2(sphere, scenario);
 
 
-	int lats=32;
-	int lons=32;
-	float radius=1.0;
+	int lats = 32;
+	int lons = 32;
+	float radius = 1.0;
 
 
 	PoolVector<Vector3> vertices;
 	PoolVector<Vector3> vertices;
 	PoolVector<Vector3> normals;
 	PoolVector<Vector3> normals;
 	PoolVector<Vector2> uvs;
 	PoolVector<Vector2> uvs;
 	PoolVector<float> tangents;
 	PoolVector<float> tangents;
-	Matrix3 tt = Matrix3(Vector3(0,1,0),Math_PI*0.5);
+	Basis tt = Basis(Vector3(0, 1, 0), Math_PI * 0.5);
 
 
-	for(int i = 1; i <= lats; i++) {
-		double lat0 = Math_PI * (-0.5 + (double) (i - 1) / lats);
-		double z0  = Math::sin(lat0);
-		double zr0 =  Math::cos(lat0);
+	for (int i = 1; i <= lats; i++) {
+		double lat0 = Math_PI * (-0.5 + (double)(i - 1) / lats);
+		double z0 = Math::sin(lat0);
+		double zr0 = Math::cos(lat0);
 
 
-		double lat1 = Math_PI * (-0.5 + (double) i / lats);
+		double lat1 = Math_PI * (-0.5 + (double)i / lats);
 		double z1 = Math::sin(lat1);
 		double z1 = Math::sin(lat1);
 		double zr1 = Math::cos(lat1);
 		double zr1 = Math::cos(lat1);
 
 
-		for(int j = lons; j >= 1; j--) {
+		for (int j = lons; j >= 1; j--) {
 
 
-			double lng0 = 2 * Math_PI * (double) (j - 1) / lons;
+			double lng0 = 2 * Math_PI * (double)(j - 1) / lons;
 			double x0 = Math::cos(lng0);
 			double x0 = Math::cos(lng0);
 			double y0 = Math::sin(lng0);
 			double y0 = Math::sin(lng0);
 
 
-			double lng1 = 2 * Math_PI * (double) (j) / lons;
+			double lng1 = 2 * Math_PI * (double)(j) / lons;
 			double x1 = Math::cos(lng1);
 			double x1 = Math::cos(lng1);
 			double y1 = Math::sin(lng1);
 			double y1 = Math::sin(lng1);
 
 
-
-			Vector3 v[4]={
-				Vector3(x1 * zr0, z0, y1 *zr0),
-				Vector3(x1 * zr1, z1, y1 *zr1),
-				Vector3(x0 * zr1, z1, y0 *zr1),
-				Vector3(x0 * zr0, z0, y0 *zr0)
+			Vector3 v[4] = {
+				Vector3(x1 * zr0, z0, y1 * zr0),
+				Vector3(x1 * zr1, z1, y1 * zr1),
+				Vector3(x0 * zr1, z1, y0 * zr1),
+				Vector3(x0 * zr0, z0, y0 * zr0)
 			};
 			};
 
 
 #define ADD_POINT(m_idx)                                                                       \
 #define ADD_POINT(m_idx)                                                                       \
@@ -364,8 +349,6 @@ EditorMaterialPreviewPlugin::EditorMaterialPreviewPlugin() {
 		tangents.push_back(1.0);                                                               \
 		tangents.push_back(1.0);                                                               \
 	}
 	}
 
 
-
-
 			ADD_POINT(0);
 			ADD_POINT(0);
 			ADD_POINT(1);
 			ADD_POINT(1);
 			ADD_POINT(2);
 			ADD_POINT(2);
@@ -378,12 +361,11 @@ EditorMaterialPreviewPlugin::EditorMaterialPreviewPlugin() {
 
 
 	Array arr;
 	Array arr;
 	arr.resize(VS::ARRAY_MAX);
 	arr.resize(VS::ARRAY_MAX);
-	arr[VS::ARRAY_VERTEX]=vertices;
-	arr[VS::ARRAY_NORMAL]=normals;
-	arr[VS::ARRAY_TANGENT]=tangents;
-	arr[VS::ARRAY_TEX_UV]=uvs;
-	VS::get_singleton()->mesh_add_surface(sphere,VS::PRIMITIVE_TRIANGLES,arr);
-
+	arr[VS::ARRAY_VERTEX] = vertices;
+	arr[VS::ARRAY_NORMAL] = normals;
+	arr[VS::ARRAY_TANGENT] = tangents;
+	arr[VS::ARRAY_TEX_UV] = uvs;
+	VS::get_singleton()->mesh_add_surface_from_arrays(sphere, VS::PRIMITIVE_TRIANGLES, arr);
 }
 }
 
 
 EditorMaterialPreviewPlugin::~EditorMaterialPreviewPlugin() {
 EditorMaterialPreviewPlugin::~EditorMaterialPreviewPlugin() {
@@ -397,30 +379,28 @@ EditorMaterialPreviewPlugin::~EditorMaterialPreviewPlugin() {
 	VS::get_singleton()->free(light_instance2);
 	VS::get_singleton()->free(light_instance2);
 	VS::get_singleton()->free(camera);
 	VS::get_singleton()->free(camera);
 	VS::get_singleton()->free(scenario);
 	VS::get_singleton()->free(scenario);
-
 }
 }
 
 
 ///////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////
 
 
 static bool _is_text_char(CharType c) {
 static bool _is_text_char(CharType c) {
 
 
-	return (c>='a' && c<='z') || (c>='A' && c<='Z') || (c>='0' && c<='9') || c=='_';
+	return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '_';
 }
 }
 
 
-bool EditorScriptPreviewPlugin::handles(const String& p_type) const {
+bool EditorScriptPreviewPlugin::handles(const String &p_type) const {
 
 
-	return ClassDB::is_type(p_type,"Script");
+	return ClassDB::is_parent_class(p_type, "Script");
 }
 }
 
 
-Ref<Texture> EditorScriptPreviewPlugin::generate(const RES& p_from) {
-
+Ref<Texture> EditorScriptPreviewPlugin::generate(const RES &p_from) {
 
 
 	Ref<Script> scr = p_from;
 	Ref<Script> scr = p_from;
 	if (scr.is_null())
 	if (scr.is_null())
 		return Ref<Texture>();
 		return Ref<Texture>();
 
 
 	String code = scr->get_source_code().strip_edges();
 	String code = scr->get_source_code().strip_edges();
-	if (code=="")
+	if (code == "")
 		return Ref<Texture>();
 		return Ref<Texture>();
 
 
 	List<String> kwors;
 	List<String> kwors;
@@ -428,107 +408,103 @@ Ref<Texture> EditorScriptPreviewPlugin::generate(const RES& p_from) {
 
 
 	Set<String> keywords;
 	Set<String> keywords;
 
 
-	for(List<String>::Element *E=kwors.front();E;E=E->next()) {
+	for (List<String>::Element *E = kwors.front(); E; E = E->next()) {
 
 
 		keywords.insert(E->get());
 		keywords.insert(E->get());
-
 	}
 	}
 
 
-
 	int line = 0;
 	int line = 0;
-	int col=0;
+	int col = 0;
 	int thumbnail_size = EditorSettings::get_singleton()->get("filesystem/file_dialog/thumbnail_size");
 	int thumbnail_size = EditorSettings::get_singleton()->get("filesystem/file_dialog/thumbnail_size");
-	thumbnail_size*=EDSCALE;
-	Image img(thumbnail_size,thumbnail_size,0,Image::FORMAT_RGBA8);
-
-
+	thumbnail_size *= EDSCALE;
+	Ref<Image> img;
+	img.instance();
+	img->create(thumbnail_size, thumbnail_size, 0, Image::FORMAT_RGBA8);
 
 
 	Color bg_color = EditorSettings::get_singleton()->get("text_editor/highlighting/background_color");
 	Color bg_color = EditorSettings::get_singleton()->get("text_editor/highlighting/background_color");
-	bg_color.a=1.0;
+	bg_color.a = 1.0;
 	Color keyword_color = EditorSettings::get_singleton()->get("text_editor/highlighting/keyword_color");
 	Color keyword_color = EditorSettings::get_singleton()->get("text_editor/highlighting/keyword_color");
 	Color text_color = EditorSettings::get_singleton()->get("text_editor/highlighting/text_color");
 	Color text_color = EditorSettings::get_singleton()->get("text_editor/highlighting/text_color");
 	Color symbol_color = EditorSettings::get_singleton()->get("text_editor/highlighting/symbol_color");
 	Color symbol_color = EditorSettings::get_singleton()->get("text_editor/highlighting/symbol_color");
 
 
-
-	for(int i=0;i<thumbnail_size;i++) {
-		for(int j=0;j<thumbnail_size;j++) {
-			img.put_pixel(i,j,bg_color);
+	for (int i = 0; i < thumbnail_size; i++) {
+		for (int j = 0; j < thumbnail_size; j++) {
+			img->put_pixel(i, j, bg_color);
 		}
 		}
-
 	}
 	}
 
 
-	bool prev_is_text=false;
-	bool in_keyword=false;
-	for(int i=0;i<code.length();i++) {
+	img->lock();
+	bool prev_is_text = false;
+	bool in_keyword = false;
+	for (int i = 0; i < code.length(); i++) {
 
 
 		CharType c = code[i];
 		CharType c = code[i];
-		if (c>32) {
-			if (col<thumbnail_size) {
+		if (c > 32) {
+			if (col < thumbnail_size) {
 				Color color = text_color;
 				Color color = text_color;
 
 
-				if (c!='_' && ((c>='!' && c<='/') || (c>=':' && c<='@') || (c>='[' && c<='`') || (c>='{' && c<='~') || c=='\t')) {
+				if (c != '_' && ((c >= '!' && c <= '/') || (c >= ':' && c <= '@') || (c >= '[' && c <= '`') || (c >= '{' && c <= '~') || c == '\t')) {
 					//make symbol a little visible
 					//make symbol a little visible
-					color=symbol_color;
-					in_keyword=false;
+					color = symbol_color;
+					in_keyword = false;
 				} else if (!prev_is_text && _is_text_char(c)) {
 				} else if (!prev_is_text && _is_text_char(c)) {
 					int pos = i;
 					int pos = i;
 
 
-					while(_is_text_char(code[pos])) {
+					while (_is_text_char(code[pos])) {
 						pos++;
 						pos++;
 					}
 					}
 					///print_line("from "+itos(i)+" to "+itos(pos));
 					///print_line("from "+itos(i)+" to "+itos(pos));
-					String word = code.substr(i,pos-i);
+					String word = code.substr(i, pos - i);
 					//print_line("found word: "+word);
 					//print_line("found word: "+word);
 					if (keywords.has(word))
 					if (keywords.has(word))
-						in_keyword=true;
+						in_keyword = true;
 
 
 				} else if (!_is_text_char(c)) {
 				} else if (!_is_text_char(c)) {
-					in_keyword=false;
+					in_keyword = false;
 				}
 				}
 
 
 				if (in_keyword)
 				if (in_keyword)
-					color=keyword_color;
+					color = keyword_color;
 
 
-				Color ul=color;
-				ul.a*=0.5;
-				img.put_pixel(col,line*2,bg_color.blend(ul));
-				img.put_pixel(col,line*2+1,color);
+				Color ul = color;
+				ul.a *= 0.5;
+				img->put_pixel(col, line * 2, bg_color.blend(ul));
+				img->put_pixel(col, line * 2 + 1, color);
 
 
-				prev_is_text=_is_text_char(c);
+				prev_is_text = _is_text_char(c);
 			}
 			}
 		} else {
 		} else {
 
 
-			prev_is_text=false;
-			in_keyword=false;
+			prev_is_text = false;
+			in_keyword = false;
 
 
-			if (c=='\n') {
-				col=0;
+			if (c == '\n') {
+				col = 0;
 				line++;
 				line++;
-				if (line>=thumbnail_size/2)
+				if (line >= thumbnail_size / 2)
 					break;
 					break;
-			} else if (c=='\t') {
-				col+=3;
+			} else if (c == '\t') {
+				col += 3;
 			}
 			}
 		}
 		}
 		col++;
 		col++;
 	}
 	}
 
 
-	Ref<ImageTexture> ptex = Ref<ImageTexture>( memnew( ImageTexture));
+	img->unlock();
 
 
-	ptex->create_from_image(img,0);
-	return ptex;
+	Ref<ImageTexture> ptex = Ref<ImageTexture>(memnew(ImageTexture));
 
 
+	ptex->create_from_image(img, 0);
+	return ptex;
 }
 }
 
 
 EditorScriptPreviewPlugin::EditorScriptPreviewPlugin() {
 EditorScriptPreviewPlugin::EditorScriptPreviewPlugin() {
-
-
 }
 }
 ///////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////
 #if 0
 #if 0
 bool EditorSamplePreviewPlugin::handles(const String& p_type) const {
 bool EditorSamplePreviewPlugin::handles(const String& p_type) const {
 
 
-	return ClassDB::is_type(p_type,"Sample");
+	return ClassDB::is_parent_class(p_type,"Sample");
 }
 }
 
 
 Ref<Texture> EditorSamplePreviewPlugin::generate(const RES& p_from) {
 Ref<Texture> EditorSamplePreviewPlugin::generate(const RES& p_from) {
@@ -795,105 +771,108 @@ EditorSamplePreviewPlugin::EditorSamplePreviewPlugin() {
 #endif
 #endif
 ///////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////
 
 
-bool EditorMeshPreviewPlugin::handles(const String& p_type) const {
+void EditorMeshPreviewPlugin::_preview_done(const Variant &p_udata) {
 
 
-	return ClassDB::is_type(p_type,"Mesh"); //any Mesh
+	preview_done = true;
 }
 }
 
 
-Ref<Texture> EditorMeshPreviewPlugin::generate(const RES& p_from) {
+void EditorMeshPreviewPlugin::_bind_methods() {
+
+	ClassDB::bind_method("_preview_done", &EditorMeshPreviewPlugin::_preview_done);
+}
+bool EditorMeshPreviewPlugin::handles(const String &p_type) const {
+
+	return ClassDB::is_parent_class(p_type, "Mesh"); //any Mesh
+}
 
 
+Ref<Texture> EditorMeshPreviewPlugin::generate(const RES &p_from) {
+
+	print_line("**Generating for mesh finally??");
 	Ref<Mesh> mesh = p_from;
 	Ref<Mesh> mesh = p_from;
-	ERR_FAIL_COND_V(mesh.is_null(),Ref<Texture>());
+	ERR_FAIL_COND_V(mesh.is_null(), Ref<Texture>());
 
 
-	VS::get_singleton()->instance_set_base(mesh_instance,mesh->get_rid());
+	VS::get_singleton()->instance_set_base(mesh_instance, mesh->get_rid());
 
 
-	AABB aabb= mesh->get_aabb();
-	Vector3 ofs = aabb.pos + aabb.size*0.5;
-	aabb.pos-=ofs;
+	Rect3 aabb = mesh->get_aabb();
+	print_line("mesh aabb: " + aabb);
+	Vector3 ofs = aabb.pos + aabb.size * 0.5;
+	aabb.pos -= ofs;
 	Transform xform;
 	Transform xform;
-	xform.basis=Matrix3().rotated(Vector3(0,1,0),-Math_PI*0.125);
-	xform.basis = Matrix3().rotated(Vector3(1,0,0),Math_PI*0.125)*xform.basis;
-	AABB rot_aabb = xform.xform(aabb);
-	float m = MAX(rot_aabb.size.x,rot_aabb.size.y)*0.5;
-	if (m==0)
+	xform.basis = Basis().rotated(Vector3(0, 1, 0), -Math_PI * 0.125);
+	xform.basis = Basis().rotated(Vector3(1, 0, 0), Math_PI * 0.125) * xform.basis;
+	Rect3 rot_aabb = xform.xform(aabb);
+	float m = MAX(rot_aabb.size.x, rot_aabb.size.y) * 0.5;
+	if (m == 0)
 		return Ref<Texture>();
 		return Ref<Texture>();
-	m=1.0/m;
-	m*=0.5;
+	m = 1.0 / m;
+	m *= 0.5;
 	//print_line("scale: "+rtos(m));
 	//print_line("scale: "+rtos(m));
-	xform.basis.scale(Vector3(m,m,m));
-	xform.origin=-xform.basis.xform(ofs); //-ofs*m;
-	xform.origin.z-=rot_aabb.size.z*2;
-	VS::get_singleton()->instance_set_transform(mesh_instance,xform);
-
+	xform.basis.scale(Vector3(m, m, m));
+	xform.origin = -xform.basis.xform(ofs); //-ofs*m;
+	xform.origin.z -= rot_aabb.size.z * 2;
+	VS::get_singleton()->instance_set_transform(mesh_instance, xform);
 
 
-
-	VS::get_singleton()->viewport_queue_screen_capture(viewport);
-	VS::get_singleton()->viewport_set_render_target_update_mode(viewport,VS::RENDER_TARGET_UPDATE_ONCE); //once used for capture
+	VS::get_singleton()->viewport_set_update_mode(viewport, VS::VIEWPORT_UPDATE_ONCE); //once used for capture
 	//print_line("queue capture!");
 	//print_line("queue capture!");
-	Image img;
 
 
-	int timeout=1000;
-	while(timeout) {
-		//print_line("try capture?");
+	preview_done = false;
+	VS::get_singleton()->request_frame_drawn_callback(this, "_preview_done", Variant());
+
+	while (!preview_done) {
 		OS::get_singleton()->delay_usec(10);
 		OS::get_singleton()->delay_usec(10);
-		img = VS::get_singleton()->viewport_get_screen_capture(viewport);
-		if (!img.empty())
-			break;
-		timeout--;
 	}
 	}
 
 
-	//print_line("captured!");
-	VS::get_singleton()->instance_set_base(mesh_instance,RID());
+	Ref<Image> img = VS::get_singleton()->VS::get_singleton()->texture_get_data(viewport_texture);
+	ERR_FAIL_COND_V(img.is_null(), Ref<ImageTexture>());
+
+	print_line("captured! " + itos(img->get_width()) + "x" + itos(img->get_height()));
+	VS::get_singleton()->instance_set_base(mesh_instance, RID());
 
 
 	int thumbnail_size = EditorSettings::get_singleton()->get("filesystem/file_dialog/thumbnail_size");
 	int thumbnail_size = EditorSettings::get_singleton()->get("filesystem/file_dialog/thumbnail_size");
-	thumbnail_size*=EDSCALE;
-	img.resize(thumbnail_size,thumbnail_size);
+	thumbnail_size *= EDSCALE;
+	img->convert(Image::FORMAT_RGBA8);
+	img->resize(thumbnail_size, thumbnail_size);
 
 
-	Ref<ImageTexture> ptex = Ref<ImageTexture>( memnew( ImageTexture ));
-	ptex->create_from_image(img,0);
+	Ref<ImageTexture> ptex = Ref<ImageTexture>(memnew(ImageTexture));
+	ptex->create_from_image(img, 0);
 	return ptex;
 	return ptex;
 }
 }
 
 
 EditorMeshPreviewPlugin::EditorMeshPreviewPlugin() {
 EditorMeshPreviewPlugin::EditorMeshPreviewPlugin() {
 
 
 	scenario = VS::get_singleton()->scenario_create();
 	scenario = VS::get_singleton()->scenario_create();
+
 	viewport = VS::get_singleton()->viewport_create();
 	viewport = VS::get_singleton()->viewport_create();
-	VS::get_singleton()->viewport_set_as_render_target(viewport,true);
-	VS::get_singleton()->viewport_set_render_target_update_mode(viewport,VS::RENDER_TARGET_UPDATE_DISABLED);
-	VS::get_singleton()->viewport_set_scenario(viewport,scenario);
-	VS::ViewportRect vr;
-	vr.x=0;
-	vr.y=0;
-	vr.width=128;
-	vr.height=128;
-	VS::get_singleton()->viewport_set_rect(viewport,vr);
+	VS::get_singleton()->viewport_set_update_mode(viewport, VS::VIEWPORT_UPDATE_DISABLED);
+	VS::get_singleton()->viewport_set_vflip(viewport, true);
+	VS::get_singleton()->viewport_set_scenario(viewport, scenario);
+	VS::get_singleton()->viewport_set_size(viewport, 128, 128);
+	VS::get_singleton()->viewport_set_transparent_background(viewport, true);
+	VS::get_singleton()->viewport_set_active(viewport, true);
+	viewport_texture = VS::get_singleton()->viewport_get_texture(viewport);
 
 
 	camera = VS::get_singleton()->camera_create();
 	camera = VS::get_singleton()->camera_create();
-	VS::get_singleton()->viewport_attach_camera(viewport,camera);
-	VS::get_singleton()->camera_set_transform(camera,Transform(Matrix3(),Vector3(0,0,3)));
+	VS::get_singleton()->viewport_attach_camera(viewport, camera);
+	VS::get_singleton()->camera_set_transform(camera, Transform(Basis(), Vector3(0, 0, 3)));
 	//VS::get_singleton()->camera_set_perspective(camera,45,0.1,10);
 	//VS::get_singleton()->camera_set_perspective(camera,45,0.1,10);
-	VS::get_singleton()->camera_set_orthogonal(camera,1.0,0.01,1000.0);
+	VS::get_singleton()->camera_set_orthogonal(camera, 1.0, 0.01, 1000.0);
 
 
 	light = VS::get_singleton()->light_create(VS::LIGHT_DIRECTIONAL);
 	light = VS::get_singleton()->light_create(VS::LIGHT_DIRECTIONAL);
-	light_instance = VS::get_singleton()->instance_create2(light,scenario);
-	VS::get_singleton()->instance_set_transform(light_instance,Transform().looking_at(Vector3(-1,-1,-1),Vector3(0,1,0)));
+	light_instance = VS::get_singleton()->instance_create2(light, scenario);
+	VS::get_singleton()->instance_set_transform(light_instance, Transform().looking_at(Vector3(-1, -1, -1), Vector3(0, 1, 0)));
 
 
 	light2 = VS::get_singleton()->light_create(VS::LIGHT_DIRECTIONAL);
 	light2 = VS::get_singleton()->light_create(VS::LIGHT_DIRECTIONAL);
-	VS::get_singleton()->light_set_color(light2,VS::LIGHT_COLOR_DIFFUSE,Color(0.7,0.7,0.7));
-	VS::get_singleton()->light_set_color(light2,VS::LIGHT_COLOR_SPECULAR,Color(0.0,0.0,0.0));
-	light_instance2 = VS::get_singleton()->instance_create2(light2,scenario);
+	VS::get_singleton()->light_set_color(light2, Color(0.7, 0.7, 0.7));
+	//VS::get_singleton()->light_set_color(light2, VS::LIGHT_COLOR_SPECULAR, Color(0.0, 0.0, 0.0));
+	light_instance2 = VS::get_singleton()->instance_create2(light2, scenario);
 
 
-	VS::get_singleton()->instance_set_transform(light_instance2,Transform().looking_at(Vector3(0,1,0),Vector3(0,0,1)));
+	VS::get_singleton()->instance_set_transform(light_instance2, Transform().looking_at(Vector3(0, 1, 0), Vector3(0, 0, 1)));
 
 
 	//sphere = VS::get_singleton()->mesh_create();
 	//sphere = VS::get_singleton()->mesh_create();
 	mesh_instance = VS::get_singleton()->instance_create();
 	mesh_instance = VS::get_singleton()->instance_create();
-	VS::get_singleton()->instance_set_scenario(mesh_instance,scenario);
-
-
-
+	VS::get_singleton()->instance_set_scenario(mesh_instance, scenario);
 }
 }
 
 
-
 EditorMeshPreviewPlugin::~EditorMeshPreviewPlugin() {
 EditorMeshPreviewPlugin::~EditorMeshPreviewPlugin() {
 
 
 	//VS::get_singleton()->free(sphere);
 	//VS::get_singleton()->free(sphere);
@@ -905,6 +884,4 @@ EditorMeshPreviewPlugin::~EditorMeshPreviewPlugin() {
 	VS::get_singleton()->free(light_instance2);
 	VS::get_singleton()->free(light_instance2);
 	VS::get_singleton()->free(camera);
 	VS::get_singleton()->free(camera);
 	VS::get_singleton()->free(scenario);
 	VS::get_singleton()->free(scenario);
-
 }
 }
-#endif

+ 35 - 25
editor/plugins/editor_preview_plugins.h

@@ -32,55 +32,58 @@
 
 
 #include "editor/editor_resource_preview.h"
 #include "editor/editor_resource_preview.h"
 
 
-#if 0
 class EditorTexturePreviewPlugin : public EditorResourcePreviewGenerator {
 class EditorTexturePreviewPlugin : public EditorResourcePreviewGenerator {
+	GDCLASS(EditorTexturePreviewPlugin, EditorResourcePreviewGenerator)
 public:
 public:
-
-	virtual bool handles(const String& p_type) const;
-	virtual Ref<Texture> generate(const RES& p_from);
+	virtual bool handles(const String &p_type) const;
+	virtual Ref<Texture> generate(const RES &p_from);
 
 
 	EditorTexturePreviewPlugin();
 	EditorTexturePreviewPlugin();
 };
 };
 
 
-
 class EditorBitmapPreviewPlugin : public EditorResourcePreviewGenerator {
 class EditorBitmapPreviewPlugin : public EditorResourcePreviewGenerator {
+	GDCLASS(EditorBitmapPreviewPlugin, EditorResourcePreviewGenerator)
 public:
 public:
-
-	virtual bool handles(const String& p_type) const;
-	virtual Ref<Texture> generate(const RES& p_from);
+	virtual bool handles(const String &p_type) const;
+	virtual Ref<Texture> generate(const RES &p_from);
 
 
 	EditorBitmapPreviewPlugin();
 	EditorBitmapPreviewPlugin();
 };
 };
 
 
-
-
 class EditorPackedScenePreviewPlugin : public EditorResourcePreviewGenerator {
 class EditorPackedScenePreviewPlugin : public EditorResourcePreviewGenerator {
 
 
-	Ref<Texture> _gen_from_imd(Ref<ResourceImportMetadata> p_imd);
 public:
 public:
-
-	virtual bool handles(const String& p_type) const;
-	virtual Ref<Texture> generate(const RES& p_from);
-	virtual Ref<Texture> generate_from_path(const String& p_path);
+	virtual bool handles(const String &p_type) const;
+	virtual Ref<Texture> generate(const RES &p_from);
+	virtual Ref<Texture> generate_from_path(const String &p_path);
 
 
 	EditorPackedScenePreviewPlugin();
 	EditorPackedScenePreviewPlugin();
 };
 };
 
 
 class EditorMaterialPreviewPlugin : public EditorResourcePreviewGenerator {
 class EditorMaterialPreviewPlugin : public EditorResourcePreviewGenerator {
 
 
+	GDCLASS(EditorMaterialPreviewPlugin, EditorResourcePreviewGenerator)
+
 	RID scenario;
 	RID scenario;
 	RID sphere;
 	RID sphere;
 	RID sphere_instance;
 	RID sphere_instance;
 	RID viewport;
 	RID viewport;
+	RID viewport_texture;
 	RID light;
 	RID light;
 	RID light_instance;
 	RID light_instance;
 	RID light2;
 	RID light2;
 	RID light_instance2;
 	RID light_instance2;
 	RID camera;
 	RID camera;
-public:
+	volatile bool preview_done;
 
 
-	virtual bool handles(const String& p_type) const;
-	virtual Ref<Texture> generate(const RES& p_from);
+	void _preview_done(const Variant &p_udata);
+
+protected:
+	static void _bind_methods();
+
+public:
+	virtual bool handles(const String &p_type) const;
+	virtual Ref<Texture> generate(const RES &p_from);
 
 
 	EditorMaterialPreviewPlugin();
 	EditorMaterialPreviewPlugin();
 	~EditorMaterialPreviewPlugin();
 	~EditorMaterialPreviewPlugin();
@@ -88,9 +91,8 @@ public:
 
 
 class EditorScriptPreviewPlugin : public EditorResourcePreviewGenerator {
 class EditorScriptPreviewPlugin : public EditorResourcePreviewGenerator {
 public:
 public:
-
-	virtual bool handles(const String& p_type) const;
-	virtual Ref<Texture> generate(const RES& p_from);
+	virtual bool handles(const String &p_type) const;
+	virtual Ref<Texture> generate(const RES &p_from);
 
 
 	EditorScriptPreviewPlugin();
 	EditorScriptPreviewPlugin();
 };
 };
@@ -108,22 +110,30 @@ public:
 #endif
 #endif
 class EditorMeshPreviewPlugin : public EditorResourcePreviewGenerator {
 class EditorMeshPreviewPlugin : public EditorResourcePreviewGenerator {
 
 
+	GDCLASS(EditorMeshPreviewPlugin, EditorResourcePreviewGenerator)
+
 	RID scenario;
 	RID scenario;
 	RID mesh_instance;
 	RID mesh_instance;
 	RID viewport;
 	RID viewport;
+	RID viewport_texture;
 	RID light;
 	RID light;
 	RID light_instance;
 	RID light_instance;
 	RID light2;
 	RID light2;
 	RID light_instance2;
 	RID light_instance2;
 	RID camera;
 	RID camera;
-public:
+	volatile bool preview_done;
 
 
-	virtual bool handles(const String& p_type) const;
-	virtual Ref<Texture> generate(const RES& p_from);
+	void _preview_done(const Variant &p_udata);
+
+protected:
+	static void _bind_methods();
+
+public:
+	virtual bool handles(const String &p_type) const;
+	virtual Ref<Texture> generate(const RES &p_from);
 
 
 	EditorMeshPreviewPlugin();
 	EditorMeshPreviewPlugin();
 	~EditorMeshPreviewPlugin();
 	~EditorMeshPreviewPlugin();
 };
 };
 
 
-#endif
 #endif // EDITORPREVIEWPLUGINS_H
 #endif // EDITORPREVIEWPLUGINS_H

+ 1 - 0
modules/squish/image_compress_squish.cpp

@@ -64,6 +64,7 @@ void image_decompress_squish(Image *p_image) {
 	} else if (p_image->get_format() == Image::FORMAT_RGTC_RG) {
 	} else if (p_image->get_format() == Image::FORMAT_RGTC_RG) {
 		squish_flags = squish::kBc5;
 		squish_flags = squish::kBc5;
 	} else {
 	} else {
+		print_line("wtf askd to decompress.. " + itos(p_image->get_format()));
 		ERR_FAIL_COND(true);
 		ERR_FAIL_COND(true);
 		return;
 		return;
 	}
 	}

+ 5 - 4
platform/x11/os_x11.cpp

@@ -34,6 +34,7 @@
 #include "print_string.h"
 #include "print_string.h"
 #include "servers/physics/physics_server_sw.h"
 #include "servers/physics/physics_server_sw.h"
 #include "servers/visual/visual_server_raster.h"
 #include "servers/visual/visual_server_raster.h"
+#include "servers/visual/visual_server_wrap_mt.h"
 #include <stdio.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <stdlib.h>
 #include <string.h>
 #include <string.h>
@@ -206,12 +207,12 @@ void OS_X11::initialize(const VideoMode &p_desired, int p_video_driver, int p_au
 
 
 #endif
 #endif
 	visual_server = memnew(VisualServerRaster);
 	visual_server = memnew(VisualServerRaster);
-#if 0
-	if (get_render_thread_mode()!=RENDER_THREAD_UNSAFE) {
 
 
-		visual_server =memnew(VisualServerWrapMT(visual_server,get_render_thread_mode()==RENDER_SEPARATE_THREAD));
+	if (get_render_thread_mode() != RENDER_THREAD_UNSAFE) {
+
+		visual_server = memnew(VisualServerWrapMT(visual_server, get_render_thread_mode() == RENDER_SEPARATE_THREAD));
 	}
 	}
-#endif
+
 	// borderless fullscreen window mode
 	// borderless fullscreen window mode
 	if (current_videomode.fullscreen) {
 	if (current_videomode.fullscreen) {
 		// needed for lxde/openbox, possibly others
 		// needed for lxde/openbox, possibly others

+ 20 - 0
scene/main/viewport.cpp

@@ -117,7 +117,11 @@ bool ViewportTexture::has_alpha() const {
 
 
 	return false;
 	return false;
 }
 }
+Ref<Image> ViewportTexture::get_data() const {
 
 
+	ERR_FAIL_COND_V(!vp, Ref<Image>());
+	return VS::get_singleton()->texture_get_data(vp->texture_rid);
+}
 void ViewportTexture::set_flags(uint32_t p_flags) {
 void ViewportTexture::set_flags(uint32_t p_flags) {
 
 
 	if (!vp)
 	if (!vp)
@@ -2516,6 +2520,16 @@ bool Viewport::get_hdr() const {
 	return hdr;
 	return hdr;
 }
 }
 
 
+void Viewport::set_usage(Usage p_usage) {
+
+	usage = p_usage;
+	VS::get_singleton()->viewport_set_usage(viewport, VS::ViewportUsage(p_usage));
+}
+
+Viewport::Usage Viewport::get_usage() const {
+	return usage;
+}
+
 void Viewport::_bind_methods() {
 void Viewport::_bind_methods() {
 
 
 	ClassDB::bind_method(D_METHOD("set_size", "size"), &Viewport::set_size);
 	ClassDB::bind_method(D_METHOD("set_size", "size"), &Viewport::set_size);
@@ -2569,6 +2583,9 @@ void Viewport::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("set_hdr", "enable"), &Viewport::set_hdr);
 	ClassDB::bind_method(D_METHOD("set_hdr", "enable"), &Viewport::set_hdr);
 	ClassDB::bind_method(D_METHOD("get_hdr"), &Viewport::get_hdr);
 	ClassDB::bind_method(D_METHOD("get_hdr"), &Viewport::get_hdr);
 
 
+	ClassDB::bind_method(D_METHOD("set_usage", "usage"), &Viewport::set_usage);
+	ClassDB::bind_method(D_METHOD("get_usage"), &Viewport::get_usage);
+
 	ClassDB::bind_method(D_METHOD("get_texture:ViewportTexture"), &Viewport::get_texture);
 	ClassDB::bind_method(D_METHOD("get_texture:ViewportTexture"), &Viewport::get_texture);
 
 
 	ClassDB::bind_method(D_METHOD("set_physics_object_picking", "enable"), &Viewport::set_physics_object_picking);
 	ClassDB::bind_method(D_METHOD("set_physics_object_picking", "enable"), &Viewport::set_physics_object_picking);
@@ -2622,6 +2639,7 @@ void Viewport::_bind_methods() {
 	ADD_PROPERTY(PropertyInfo(Variant::INT, "msaa", PROPERTY_HINT_ENUM, "Disabled,2x,4x,8x,16x"), "set_msaa", "get_msaa");
 	ADD_PROPERTY(PropertyInfo(Variant::INT, "msaa", PROPERTY_HINT_ENUM, "Disabled,2x,4x,8x,16x"), "set_msaa", "get_msaa");
 	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "hdr"), "set_hdr", "get_hdr");
 	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "hdr"), "set_hdr", "get_hdr");
 	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "disable_3d"), "set_disable_3d", "is_3d_disabled");
 	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "disable_3d"), "set_disable_3d", "is_3d_disabled");
+	ADD_PROPERTY(PropertyInfo(Variant::INT, "usage", PROPERTY_HINT_ENUM, "2D,2D No-Sampling,3D,3D No-Effects"), "set_usage", "get_usage");
 	ADD_GROUP("Render Target", "render_target_");
 	ADD_GROUP("Render Target", "render_target_");
 	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "render_target_v_flip"), "set_vflip", "get_vflip");
 	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "render_target_v_flip"), "set_vflip", "get_vflip");
 	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "render_target_clear_on_new_frame"), "set_clear_on_new_frame", "get_clear_on_new_frame");
 	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "render_target_clear_on_new_frame"), "set_clear_on_new_frame", "get_clear_on_new_frame");
@@ -2730,6 +2748,8 @@ Viewport::Viewport() {
 
 
 	msaa = MSAA_DISABLED;
 	msaa = MSAA_DISABLED;
 	hdr = false;
 	hdr = false;
+
+	usage = USAGE_3D;
 }
 }
 
 
 Viewport::~Viewport() {
 Viewport::~Viewport() {

+ 15 - 0
scene/main/viewport.h

@@ -77,6 +77,8 @@ public:
 	virtual void set_flags(uint32_t p_flags);
 	virtual void set_flags(uint32_t p_flags);
 	virtual uint32_t get_flags() const;
 	virtual uint32_t get_flags() const;
 
 
+	virtual Ref<Image> get_data() const;
+
 	ViewportTexture();
 	ViewportTexture();
 	~ViewportTexture();
 	~ViewportTexture();
 };
 };
@@ -113,6 +115,13 @@ public:
 		MSAA_16X,
 		MSAA_16X,
 	};
 	};
 
 
+	enum Usage {
+		USAGE_2D,
+		USAGE_2D_NO_SAMPLING,
+		USAGE_3D,
+		USAGE_3D_NO_EFFECTS,
+	};
+
 private:
 private:
 	friend class ViewportTexture;
 	friend class ViewportTexture;
 
 
@@ -195,6 +204,8 @@ private:
 	RID texture_rid;
 	RID texture_rid;
 	uint32_t texture_flags;
 	uint32_t texture_flags;
 
 
+	Usage usage;
+
 	int shadow_atlas_size;
 	int shadow_atlas_size;
 	ShadowAtlasQuadrantSubdiv shadow_atlas_quadrant_subdiv[4];
 	ShadowAtlasQuadrantSubdiv shadow_atlas_quadrant_subdiv[4];
 
 
@@ -416,6 +427,9 @@ public:
 
 
 	virtual String get_configuration_warning() const;
 	virtual String get_configuration_warning() const;
 
 
+	void set_usage(Usage p_usage);
+	Usage get_usage() const;
+
 	Viewport();
 	Viewport();
 	~Viewport();
 	~Viewport();
 };
 };
@@ -423,5 +437,6 @@ public:
 VARIANT_ENUM_CAST(Viewport::UpdateMode);
 VARIANT_ENUM_CAST(Viewport::UpdateMode);
 VARIANT_ENUM_CAST(Viewport::ShadowAtlasQuadrantSubdiv);
 VARIANT_ENUM_CAST(Viewport::ShadowAtlasQuadrantSubdiv);
 VARIANT_ENUM_CAST(Viewport::MSAA);
 VARIANT_ENUM_CAST(Viewport::MSAA);
+VARIANT_ENUM_CAST(Viewport::Usage);
 
 
 #endif
 #endif

+ 1 - 0
scene/resources/mesh.cpp

@@ -693,6 +693,7 @@ void ArrayMesh::add_surface(uint32_t p_format, PrimitiveType p_primitive, const
 	Surface s;
 	Surface s;
 	s.aabb = p_aabb;
 	s.aabb = p_aabb;
 	surfaces.push_back(s);
 	surfaces.push_back(s);
+	_recompute_aabb();
 
 
 	VisualServer::get_singleton()->mesh_add_surface(mesh, p_format, (VS::PrimitiveType)p_primitive, p_array, p_vertex_count, p_index_array, p_index_count, p_aabb, p_blend_shapes, p_bone_aabbs);
 	VisualServer::get_singleton()->mesh_add_surface(mesh, p_format, (VS::PrimitiveType)p_primitive, p_array, p_vertex_count, p_index_array, p_index_count, p_aabb, p_blend_shapes, p_bone_aabbs);
 }
 }

+ 4 - 0
scene/resources/texture.cpp

@@ -1781,6 +1781,10 @@ float GradientTexture::get_offset(int pos) const {
 	return 0; //TODO: Maybe throw some error instead?
 	return 0; //TODO: Maybe throw some error instead?
 }
 }
 
 
+Ref<Image> GradientTexture::get_data() const {
+	return VisualServer::get_singleton()->texture_get_data(texture);
+}
+
 void GradientTexture::set_color(int pos, const Color &color) {
 void GradientTexture::set_color(int pos, const Color &color) {
 	if (points.size() <= pos) {
 	if (points.size() <= pos) {
 		points.resize(pos + 1);
 		points.resize(pos + 1);

+ 2 - 0
scene/resources/texture.h

@@ -539,6 +539,8 @@ public:
 		return pointFirst.color.linear_interpolate(pointSecond.color, (p_offset - pointFirst.offset) / (pointSecond.offset - pointFirst.offset));
 		return pointFirst.color.linear_interpolate(pointSecond.color, (p_offset - pointFirst.offset) / (pointSecond.offset - pointFirst.offset));
 	}
 	}
 
 
+	virtual Ref<Image> get_data() const;
+
 	int get_points_count() const;
 	int get_points_count() const;
 
 
 	GradientTexture();
 	GradientTexture();

+ 20 - 1
servers/server_wrap_mt_common.h

@@ -41,8 +41,9 @@
 	}
 	}
 
 
 #define FUNCRID(m_type)                                                                    \
 #define FUNCRID(m_type)                                                                    \
+	List<RID> m_type##_id_pool;                                                            \
 	int m_type##allocn() {                                                                 \
 	int m_type##allocn() {                                                                 \
-		for (int i = 0; i < m_type##_pool_max_size; i++) {                                 \
+		for (int i = 0; i < pool_max_size; i++) {                                          \
 			m_type##_id_pool.push_back(server_name->m_type##_create());                    \
 			m_type##_id_pool.push_back(server_name->m_type##_create());                    \
 		}                                                                                  \
 		}                                                                                  \
 		return 0;                                                                          \
 		return 0;                                                                          \
@@ -747,3 +748,21 @@
 			server_name->m_type(p1, p2, p3, p4, p5, p6, p7, p8);                                                        \
 			server_name->m_type(p1, p2, p3, p4, p5, p6, p7, p8);                                                        \
 		}                                                                                                               \
 		}                                                                                                               \
 	}
 	}
+
+#define FUNC9(m_type, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7, m_arg8, m_arg9)                                \
+	virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6, m_arg7 p7, m_arg8 p8, m_arg9 p9) { \
+		if (Thread::get_caller_ID() != server_thread) {                                                                      \
+			command_queue.push(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6, p7, p8, p9);                        \
+		} else {                                                                                                             \
+			server_name->m_type(p1, p2, p3, p4, p5, p6, p7, p8, p9);                                                         \
+		}                                                                                                                    \
+	}
+
+#define FUNC10(m_type, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7, m_arg8, m_arg9, m_arg10)                                   \
+	virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6, m_arg7 p7, m_arg8 p8, m_arg9 p9, m_arg10 p10) { \
+		if (Thread::get_caller_ID() != server_thread) {                                                                                   \
+			command_queue.push(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10);                                \
+		} else {                                                                                                                          \
+			server_name->m_type(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10);                                                                 \
+		}                                                                                                                                 \
+	}

+ 1 - 0
servers/visual/rasterizer.h

@@ -468,6 +468,7 @@ public:
 	enum RenderTargetFlags {
 	enum RenderTargetFlags {
 		RENDER_TARGET_VFLIP,
 		RENDER_TARGET_VFLIP,
 		RENDER_TARGET_TRANSPARENT,
 		RENDER_TARGET_TRANSPARENT,
+		RENDER_TARGET_NO_3D_EFFECTS,
 		RENDER_TARGET_NO_3D,
 		RENDER_TARGET_NO_3D,
 		RENDER_TARGET_NO_SAMPLING,
 		RENDER_TARGET_NO_SAMPLING,
 		RENDER_TARGET_HDR,
 		RENDER_TARGET_HDR,

+ 29 - 0
servers/visual/visual_server_raster.cpp

@@ -74,6 +74,19 @@ void VisualServerRaster::free(RID p_rid) {
 
 
 /* EVENT QUEUING */
 /* EVENT QUEUING */
 
 
+void VisualServerRaster::request_frame_drawn_callback(Object *p_where, const StringName &p_method, const Variant &p_userdata) {
+
+	ERR_FAIL_NULL(p_where);
+	FrameDrawnCallbacks fdc;
+	fdc.object = p_where->get_instance_ID();
+	fdc.method = p_method;
+	fdc.param = p_userdata;
+
+	frame_drawn_callbacks.push_back(fdc);
+
+	print_line("added callback to draw");
+}
+
 void VisualServerRaster::draw() {
 void VisualServerRaster::draw() {
 
 
 	/*
 	/*
@@ -92,6 +105,22 @@ void VisualServerRaster::draw() {
 	//_draw_cursors_and_margins();
 	//_draw_cursors_and_margins();
 	VSG::rasterizer->end_frame();
 	VSG::rasterizer->end_frame();
 	//draw_extra_frame=VS:rasterizer->needs_to_draw_next_frame();
 	//draw_extra_frame=VS:rasterizer->needs_to_draw_next_frame();
+
+	while (frame_drawn_callbacks.front()) {
+
+		Object *obj = ObjectDB::get_instance(frame_drawn_callbacks.front()->get().object);
+		if (obj) {
+			Variant::CallError ce;
+			const Variant *v = &frame_drawn_callbacks.front()->get().param;
+			obj->call(frame_drawn_callbacks.front()->get().method, &v, 1, ce);
+			if (ce.error != Variant::CallError::CALL_OK) {
+				String err = Variant::get_call_error_text(obj, frame_drawn_callbacks.front()->get().method, &v, 1, ce);
+				ERR_PRINTS("Error calling frame drawn function: " + err);
+			}
+		}
+
+		frame_drawn_callbacks.pop_front();
+	}
 }
 }
 void VisualServerRaster::sync() {
 void VisualServerRaster::sync() {
 }
 }

+ 12 - 2
servers/visual/visual_server_raster.h

@@ -61,6 +61,15 @@ class VisualServerRaster : public VisualServer {
 	bool draw_extra_frame;
 	bool draw_extra_frame;
 	RID test_cube;
 	RID test_cube;
 
 
+	struct FrameDrawnCallbacks {
+
+		ObjectID object;
+		StringName method;
+		Variant param;
+	};
+
+	List<FrameDrawnCallbacks> frame_drawn_callbacks;
+
 #if 0
 #if 0
 	struct Room {
 	struct Room {
 
 
@@ -632,7 +641,6 @@ public:
 	BIND1RC(uint32_t, texture_get_width, RID)
 	BIND1RC(uint32_t, texture_get_width, RID)
 	BIND1RC(uint32_t, texture_get_height, RID)
 	BIND1RC(uint32_t, texture_get_height, RID)
 	BIND3(texture_set_size_override, RID, int, int)
 	BIND3(texture_set_size_override, RID, int, int)
-	BIND2RC(RID, texture_create_radiance_cubemap, RID, int)
 
 
 	BIND3(texture_set_detect_3d_callback, RID, TextureDetectCallback, void *)
 	BIND3(texture_set_detect_3d_callback, RID, TextureDetectCallback, void *)
 	BIND3(texture_set_detect_srgb_callback, RID, TextureDetectCallback, void *)
 	BIND3(texture_set_detect_srgb_callback, RID, TextureDetectCallback, void *)
@@ -922,6 +930,7 @@ public:
 	BIND3(viewport_set_shadow_atlas_quadrant_subdivision, RID, int, int)
 	BIND3(viewport_set_shadow_atlas_quadrant_subdivision, RID, int, int)
 	BIND2(viewport_set_msaa, RID, ViewportMSAA)
 	BIND2(viewport_set_msaa, RID, ViewportMSAA)
 	BIND2(viewport_set_hdr, RID, bool)
 	BIND2(viewport_set_hdr, RID, bool)
+	BIND2(viewport_set_usage, RID, ViewportUsage)
 
 
 /* ENVIRONMENT API */
 /* ENVIRONMENT API */
 
 
@@ -944,7 +953,6 @@ public:
 	BIND6(environment_set_dof_blur_near, RID, bool, float, float, float, EnvironmentDOFBlurQuality)
 	BIND6(environment_set_dof_blur_near, RID, bool, float, float, float, EnvironmentDOFBlurQuality)
 	BIND6(environment_set_dof_blur_far, RID, bool, float, float, float, EnvironmentDOFBlurQuality)
 	BIND6(environment_set_dof_blur_far, RID, bool, float, float, float, EnvironmentDOFBlurQuality)
 	BIND10(environment_set_glow, RID, bool, int, float, float, float, EnvironmentGlowBlendMode, float, float, bool)
 	BIND10(environment_set_glow, RID, bool, int, float, float, float, EnvironmentGlowBlendMode, float, float, bool)
-	BIND5(environment_set_fog, RID, bool, float, float, RID)
 
 
 	BIND9(environment_set_tonemap, RID, EnvironmentToneMapper, float, float, bool, float, float, float, float)
 	BIND9(environment_set_tonemap, RID, EnvironmentToneMapper, float, float, bool, float, float, float, float)
 
 
@@ -1100,6 +1108,8 @@ public:
 
 
 	/* EVENT QUEUING */
 	/* EVENT QUEUING */
 
 
+	virtual void request_frame_drawn_callback(Object *p_where, const StringName &p_method, const Variant &p_userdata);
+
 	virtual void draw();
 	virtual void draw();
 	virtual void sync();
 	virtual void sync();
 	virtual bool has_changed() const;
 	virtual bool has_changed() const;

+ 41 - 2
servers/visual/visual_server_viewport.cpp

@@ -88,7 +88,7 @@ void VisualServerViewport::_draw_viewport(Viewport *p_viewport) {
 		}
 		}
 	}
 	}
 
 
-	if (!p_viewport->disable_3d && p_viewport->camera.is_valid()) {
+	if (!p_viewport->disable_3d && !p_viewport->disable_3d_by_usage && p_viewport->camera.is_valid()) {
 
 
 		VSG::scene->render_camera(p_viewport->camera, p_viewport->scenario, p_viewport->size, p_viewport->shadow_atlas);
 		VSG::scene->render_camera(p_viewport->camera, p_viewport->scenario, p_viewport->size, p_viewport->shadow_atlas);
 	}
 	}
@@ -409,7 +409,8 @@ void VisualServerViewport::viewport_set_disable_3d(RID p_viewport, bool p_disabl
 	ERR_FAIL_COND(!viewport);
 	ERR_FAIL_COND(!viewport);
 
 
 	viewport->disable_3d = p_disable;
 	viewport->disable_3d = p_disable;
-	VSG::storage->render_target_set_flag(viewport->render_target, RasterizerStorage::RENDER_TARGET_NO_3D, p_disable);
+	//VSG::storage->render_target_set_flag(viewport->render_target, RasterizerStorage::RENDER_TARGET_NO_3D, p_disable);
+	//this should be just for disabling rendering of 3D, to actually disable it, set usage
 }
 }
 
 
 void VisualServerViewport::viewport_attach_camera(RID p_viewport, RID p_camera) {
 void VisualServerViewport::viewport_attach_camera(RID p_viewport, RID p_camera) {
@@ -518,6 +519,44 @@ void VisualServerViewport::viewport_set_hdr(RID p_viewport, bool p_enabled) {
 	VSG::storage->render_target_set_flag(viewport->render_target, RasterizerStorage::RENDER_TARGET_HDR, p_enabled);
 	VSG::storage->render_target_set_flag(viewport->render_target, RasterizerStorage::RENDER_TARGET_HDR, p_enabled);
 }
 }
 
 
+void VisualServerViewport::viewport_set_usage(RID p_viewport, VS::ViewportUsage p_usage) {
+
+	Viewport *viewport = viewport_owner.getornull(p_viewport);
+	ERR_FAIL_COND(!viewport);
+
+	switch (p_usage) {
+		case VS::VIEWPORT_USAGE_2D: {
+
+			VSG::storage->render_target_set_flag(viewport->render_target, RasterizerStorage::RENDER_TARGET_NO_3D, true);
+			VSG::storage->render_target_set_flag(viewport->render_target, RasterizerStorage::RENDER_TARGET_NO_3D_EFFECTS, true);
+			VSG::storage->render_target_set_flag(viewport->render_target, RasterizerStorage::RENDER_TARGET_NO_SAMPLING, false);
+
+			viewport->disable_3d_by_usage = true;
+		} break;
+		case VS::VIEWPORT_USAGE_2D_NO_SAMPLING: {
+
+			VSG::storage->render_target_set_flag(viewport->render_target, RasterizerStorage::RENDER_TARGET_NO_3D, true);
+			VSG::storage->render_target_set_flag(viewport->render_target, RasterizerStorage::RENDER_TARGET_NO_3D_EFFECTS, true);
+			VSG::storage->render_target_set_flag(viewport->render_target, RasterizerStorage::RENDER_TARGET_NO_SAMPLING, true);
+			viewport->disable_3d_by_usage = true;
+		} break;
+		case VS::VIEWPORT_USAGE_3D: {
+
+			VSG::storage->render_target_set_flag(viewport->render_target, RasterizerStorage::RENDER_TARGET_NO_3D, false);
+			VSG::storage->render_target_set_flag(viewport->render_target, RasterizerStorage::RENDER_TARGET_NO_3D_EFFECTS, false);
+			VSG::storage->render_target_set_flag(viewport->render_target, RasterizerStorage::RENDER_TARGET_NO_SAMPLING, false);
+			viewport->disable_3d_by_usage = false;
+		} break;
+		case VS::VIEWPORT_USAGE_3D_NO_EFFECTS: {
+
+			VSG::storage->render_target_set_flag(viewport->render_target, RasterizerStorage::RENDER_TARGET_NO_3D, false);
+			VSG::storage->render_target_set_flag(viewport->render_target, RasterizerStorage::RENDER_TARGET_NO_3D_EFFECTS, true);
+			VSG::storage->render_target_set_flag(viewport->render_target, RasterizerStorage::RENDER_TARGET_NO_SAMPLING, false);
+			viewport->disable_3d_by_usage = false;
+		} break;
+	}
+}
+
 bool VisualServerViewport::free(RID p_rid) {
 bool VisualServerViewport::free(RID p_rid) {
 
 
 	if (viewport_owner.owns(p_rid)) {
 	if (viewport_owner.owns(p_rid)) {

+ 3 - 0
servers/visual/visual_server_viewport.h

@@ -59,6 +59,7 @@ public:
 		bool hide_canvas;
 		bool hide_canvas;
 		bool disable_environment;
 		bool disable_environment;
 		bool disable_3d;
 		bool disable_3d;
+		bool disable_3d_by_usage;
 
 
 		RID shadow_atlas;
 		RID shadow_atlas;
 		int shadow_atlas_size;
 		int shadow_atlas_size;
@@ -101,6 +102,7 @@ public:
 			viewport_to_screen = 0;
 			viewport_to_screen = 0;
 			shadow_atlas_size = 0;
 			shadow_atlas_size = 0;
 			disable_3d = false;
 			disable_3d = false;
+			disable_3d_by_usage = false;
 		}
 		}
 	};
 	};
 
 
@@ -164,6 +166,7 @@ public:
 
 
 	void viewport_set_msaa(RID p_viewport, VS::ViewportMSAA p_msaa);
 	void viewport_set_msaa(RID p_viewport, VS::ViewportMSAA p_msaa);
 	void viewport_set_hdr(RID p_viewport, bool p_enabled);
 	void viewport_set_hdr(RID p_viewport, bool p_enabled);
+	void viewport_set_usage(RID p_viewport, VS::ViewportUsage p_usage);
 
 
 	void draw_viewports();
 	void draw_viewports();
 
 

+ 193 - 0
servers/visual/visual_server_wrap_mt.cpp

@@ -0,0 +1,193 @@
+/*************************************************************************/
+/*  visual_server_wrap_mt.cpp                                            */
+/*************************************************************************/
+/*                       This file is part of:                           */
+/*                           GODOT ENGINE                                */
+/*                    http://www.godotengine.org                         */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur.                 */
+/*                                                                       */
+/* 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 "visual_server_wrap_mt.h"
+#include "global_config.h"
+#include "os/os.h"
+
+void VisualServerWrapMT::thread_exit() {
+
+	exit = true;
+}
+
+void VisualServerWrapMT::thread_draw() {
+
+	draw_mutex->lock();
+
+	draw_pending--;
+	bool draw = (draw_pending == 0); // only draw when no more flushes are pending
+
+	draw_mutex->unlock();
+
+	if (draw) {
+
+		visual_server->draw();
+	}
+}
+
+void VisualServerWrapMT::thread_flush() {
+
+	draw_mutex->lock();
+
+	draw_pending--;
+
+	draw_mutex->unlock();
+}
+
+void VisualServerWrapMT::_thread_callback(void *_instance) {
+
+	VisualServerWrapMT *vsmt = reinterpret_cast<VisualServerWrapMT *>(_instance);
+
+	vsmt->thread_loop();
+}
+
+void VisualServerWrapMT::thread_loop() {
+
+	server_thread = Thread::get_caller_ID();
+
+	OS::get_singleton()->make_rendering_thread();
+
+	visual_server->init();
+
+	exit = false;
+	draw_thread_up = true;
+	while (!exit) {
+		// flush commands one by one, until exit is requested
+		command_queue.wait_and_flush_one();
+	}
+
+	command_queue.flush_all(); // flush all
+
+	visual_server->finish();
+}
+
+/* EVENT QUEUING */
+
+void VisualServerWrapMT::sync() {
+
+	if (create_thread) {
+
+		/* TODO: sync with the thread */
+
+		/*
+		ERR_FAIL_COND(!draw_mutex);
+		draw_mutex->lock();
+		draw_pending++; //cambiar por un saferefcount
+		draw_mutex->unlock();
+		*/
+		//command_queue.push( this, &VisualServerWrapMT::thread_flush);
+	} else {
+
+		command_queue.flush_all(); //flush all pending from other threads
+	}
+}
+
+void VisualServerWrapMT::draw() {
+
+	if (create_thread) {
+
+		/* TODO: Make it draw
+		ERR_FAIL_COND(!draw_mutex);
+		draw_mutex->lock();
+		draw_pending++; //cambiar por un saferefcount
+		draw_mutex->unlock();
+
+		command_queue.push( this, &VisualServerWrapMT::thread_draw);
+		*/
+	} else {
+
+		visual_server->draw();
+	}
+}
+
+void VisualServerWrapMT::init() {
+
+	if (create_thread) {
+
+		draw_mutex = Mutex::create();
+		print_line("CREATING RENDER THREAD");
+		OS::get_singleton()->release_rendering_thread();
+		if (create_thread) {
+			thread = Thread::create(_thread_callback, this);
+			print_line("STARTING RENDER THREAD");
+		}
+		while (!draw_thread_up) {
+			OS::get_singleton()->delay_usec(1000);
+		}
+		print_line("DONE RENDER THREAD");
+	} else {
+
+		visual_server->init();
+	}
+}
+
+void VisualServerWrapMT::finish() {
+
+	if (thread) {
+
+		command_queue.push(this, &VisualServerWrapMT::thread_exit);
+		Thread::wait_to_finish(thread);
+		memdelete(thread);
+
+		texture_free_cached_ids();
+		//mesh_free_cached_ids();
+
+		thread = NULL;
+	} else {
+		visual_server->finish();
+	}
+
+	if (draw_mutex)
+		memdelete(draw_mutex);
+}
+
+VisualServerWrapMT::VisualServerWrapMT(VisualServer *p_contained, bool p_create_thread)
+	: command_queue(p_create_thread) {
+
+	visual_server = p_contained;
+	create_thread = p_create_thread;
+	thread = NULL;
+	draw_mutex = NULL;
+	draw_pending = 0;
+	draw_thread_up = false;
+	alloc_mutex = Mutex::create();
+	pool_max_size = GLOBAL_DEF("memory/servers/thread_rid_prealloc_amount", 20);
+
+	if (!p_create_thread) {
+		server_thread = Thread::get_caller_ID();
+	} else {
+		server_thread = 0;
+	}
+}
+
+VisualServerWrapMT::~VisualServerWrapMT() {
+
+	memdelete(visual_server);
+	memdelete(alloc_mutex);
+	//finish();
+}

+ 571 - 0
servers/visual/visual_server_wrap_mt.h

@@ -0,0 +1,571 @@
+/*************************************************************************/
+/*  visual_server_wrap_mt.h                                              */
+/*************************************************************************/
+/*                       This file is part of:                           */
+/*                           GODOT ENGINE                                */
+/*                    http://www.godotengine.org                         */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur.                 */
+/*                                                                       */
+/* 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.                */
+/*************************************************************************/
+#ifndef VISUAL_SERVER_WRAP_MT_H
+#define VISUAL_SERVER_WRAP_MT_H
+
+#include "command_queue_mt.h"
+#include "os/thread.h"
+#include "servers/visual_server.h"
+
+/**
+	@author Juan Linietsky <[email protected]>
+*/
+class VisualServerWrapMT : public VisualServer {
+
+	// the real visual server
+	mutable VisualServer *visual_server;
+
+	mutable CommandQueueMT command_queue;
+
+	static void _thread_callback(void *_instance);
+	void thread_loop();
+
+	Thread::ID server_thread;
+	volatile bool exit;
+	Thread *thread;
+	volatile bool draw_thread_up;
+	bool create_thread;
+
+	Mutex *draw_mutex;
+	int draw_pending;
+	void thread_draw();
+	void thread_flush();
+
+	void thread_exit();
+
+	Mutex *alloc_mutex;
+
+	int pool_max_size;
+
+//#define DEBUG_SYNC
+
+#ifdef DEBUG_SYNC
+#define SYNC_DEBUG print_line("sync on: " + String(__FUNCTION__));
+#else
+#define SYNC_DEBUG
+#endif
+
+public:
+#define ServerName VisualServer
+#define ServerNameWrapMT VisualServerWrapMT
+#define server_name visual_server
+#include "servers/server_wrap_mt_common.h"
+
+	/* EVENT QUEUING */
+	FUNCRID(texture)
+	FUNC5(texture_allocate, RID, int, int, Image::Format, uint32_t)
+	FUNC3(texture_set_data, RID, const Ref<Image> &, CubeMapSide)
+	FUNC2RC(Ref<Image>, texture_get_data, RID, CubeMapSide)
+	FUNC2(texture_set_flags, RID, uint32_t)
+	FUNC1RC(uint32_t, texture_get_flags, RID)
+	FUNC1RC(Image::Format, texture_get_format, RID)
+	FUNC1RC(uint32_t, texture_get_texid, RID)
+	FUNC1RC(uint32_t, texture_get_width, RID)
+	FUNC1RC(uint32_t, texture_get_height, RID)
+	FUNC3(texture_set_size_override, RID, int, int)
+
+	FUNC3(texture_set_detect_3d_callback, RID, TextureDetectCallback, void *)
+	FUNC3(texture_set_detect_srgb_callback, RID, TextureDetectCallback, void *)
+
+	FUNC2(texture_set_path, RID, const String &)
+	FUNC1RC(String, texture_get_path, RID)
+	FUNC1(texture_set_shrink_all_x2_on_set_data, bool)
+	FUNC1(texture_debug_usage, List<TextureInfo> *)
+
+	FUNC1(textures_keep_original, bool)
+
+	/* SKY API */
+
+	FUNC0R(RID, sky_create)
+	FUNC3(sky_set_texture, RID, RID, int)
+
+	/* SHADER API */
+
+	FUNC0R(RID, shader_create)
+
+	FUNC2(shader_set_code, RID, const String &)
+	FUNC1RC(String, shader_get_code, RID)
+
+	FUNC2C(shader_get_param_list, RID, List<PropertyInfo> *)
+
+	FUNC3(shader_set_default_texture_param, RID, const StringName &, RID)
+	FUNC2RC(RID, shader_get_default_texture_param, RID, const StringName &)
+
+	/* COMMON MATERIAL API */
+
+	FUNC0R(RID, material_create)
+
+	FUNC2(material_set_shader, RID, RID)
+	FUNC1RC(RID, material_get_shader, RID)
+
+	FUNC3(material_set_param, RID, const StringName &, const Variant &)
+	FUNC2RC(Variant, material_get_param, RID, const StringName &)
+
+	FUNC2(material_set_line_width, RID, float)
+
+	/* MESH API */
+
+	FUNC0R(RID, mesh_create)
+
+	FUNC10(mesh_add_surface, RID, uint32_t, PrimitiveType, const PoolVector<uint8_t> &, int, const PoolVector<uint8_t> &, int, const Rect3 &, const Vector<PoolVector<uint8_t> > &, const Vector<Rect3> &)
+
+	FUNC2(mesh_set_blend_shape_count, RID, int)
+	FUNC1RC(int, mesh_get_blend_shape_count, RID)
+
+	FUNC2(mesh_set_blend_shape_mode, RID, BlendShapeMode)
+	FUNC1RC(BlendShapeMode, mesh_get_blend_shape_mode, RID)
+
+	FUNC3(mesh_surface_set_material, RID, int, RID)
+	FUNC2RC(RID, mesh_surface_get_material, RID, int)
+
+	FUNC2RC(int, mesh_surface_get_array_len, RID, int)
+	FUNC2RC(int, mesh_surface_get_array_index_len, RID, int)
+
+	FUNC2RC(PoolVector<uint8_t>, mesh_surface_get_array, RID, int)
+	FUNC2RC(PoolVector<uint8_t>, mesh_surface_get_index_array, RID, int)
+
+	FUNC2RC(uint32_t, mesh_surface_get_format, RID, int)
+	FUNC2RC(PrimitiveType, mesh_surface_get_primitive_type, RID, int)
+
+	FUNC2RC(Rect3, mesh_surface_get_aabb, RID, int)
+	FUNC2RC(Vector<PoolVector<uint8_t> >, mesh_surface_get_blend_shapes, RID, int)
+	FUNC2RC(Vector<Rect3>, mesh_surface_get_skeleton_aabb, RID, int)
+
+	FUNC2(mesh_remove_surface, RID, int)
+	FUNC1RC(int, mesh_get_surface_count, RID)
+
+	FUNC2(mesh_set_custom_aabb, RID, const Rect3 &)
+	FUNC1RC(Rect3, mesh_get_custom_aabb, RID)
+
+	FUNC1(mesh_clear, RID)
+
+	/* MULTIMESH API */
+
+	FUNC0R(RID, multimesh_create)
+
+	FUNC4(multimesh_allocate, RID, int, MultimeshTransformFormat, MultimeshColorFormat)
+	FUNC1RC(int, multimesh_get_instance_count, RID)
+
+	FUNC2(multimesh_set_mesh, RID, RID)
+	FUNC3(multimesh_instance_set_transform, RID, int, const Transform &)
+	FUNC3(multimesh_instance_set_transform_2d, RID, int, const Transform2D &)
+	FUNC3(multimesh_instance_set_color, RID, int, const Color &)
+
+	FUNC1RC(RID, multimesh_get_mesh, RID)
+	FUNC1RC(Rect3, multimesh_get_aabb, RID)
+
+	FUNC2RC(Transform, multimesh_instance_get_transform, RID, int)
+	FUNC2RC(Transform2D, multimesh_instance_get_transform_2d, RID, int)
+	FUNC2RC(Color, multimesh_instance_get_color, RID, int)
+
+	FUNC2(multimesh_set_visible_instances, RID, int)
+	FUNC1RC(int, multimesh_get_visible_instances, RID)
+
+	/* IMMEDIATE API */
+
+	FUNC0R(RID, immediate_create)
+	FUNC3(immediate_begin, RID, PrimitiveType, RID)
+	FUNC2(immediate_vertex, RID, const Vector3 &)
+	FUNC2(immediate_normal, RID, const Vector3 &)
+	FUNC2(immediate_tangent, RID, const Plane &)
+	FUNC2(immediate_color, RID, const Color &)
+	FUNC2(immediate_uv, RID, const Vector2 &)
+	FUNC2(immediate_uv2, RID, const Vector2 &)
+	FUNC1(immediate_end, RID)
+	FUNC1(immediate_clear, RID)
+	FUNC2(immediate_set_material, RID, RID)
+	FUNC1RC(RID, immediate_get_material, RID)
+
+	/* SKELETON API */
+
+	FUNC0R(RID, skeleton_create)
+	FUNC3(skeleton_allocate, RID, int, bool)
+	FUNC1RC(int, skeleton_get_bone_count, RID)
+	FUNC3(skeleton_bone_set_transform, RID, int, const Transform &)
+	FUNC2RC(Transform, skeleton_bone_get_transform, RID, int)
+	FUNC3(skeleton_bone_set_transform_2d, RID, int, const Transform2D &)
+	FUNC2RC(Transform2D, skeleton_bone_get_transform_2d, RID, int)
+
+	/* Light API */
+
+	FUNC1R(RID, light_create, LightType)
+
+	FUNC2(light_set_color, RID, const Color &)
+	FUNC3(light_set_param, RID, LightParam, float)
+	FUNC2(light_set_shadow, RID, bool)
+	FUNC2(light_set_shadow_color, RID, const Color &)
+	FUNC2(light_set_projector, RID, RID)
+	FUNC2(light_set_negative, RID, bool)
+	FUNC2(light_set_cull_mask, RID, uint32_t)
+
+	FUNC2(light_omni_set_shadow_mode, RID, LightOmniShadowMode)
+	FUNC2(light_omni_set_shadow_detail, RID, LightOmniShadowDetail)
+
+	FUNC2(light_directional_set_shadow_mode, RID, LightDirectionalShadowMode)
+	FUNC2(light_directional_set_blend_splits, RID, bool)
+
+	/* PROBE API */
+
+	FUNC0R(RID, reflection_probe_create)
+
+	FUNC2(reflection_probe_set_update_mode, RID, ReflectionProbeUpdateMode)
+	FUNC2(reflection_probe_set_intensity, RID, float)
+	FUNC2(reflection_probe_set_interior_ambient, RID, const Color &)
+	FUNC2(reflection_probe_set_interior_ambient_energy, RID, float)
+	FUNC2(reflection_probe_set_interior_ambient_probe_contribution, RID, float)
+	FUNC2(reflection_probe_set_max_distance, RID, float)
+	FUNC2(reflection_probe_set_extents, RID, const Vector3 &)
+	FUNC2(reflection_probe_set_origin_offset, RID, const Vector3 &)
+	FUNC2(reflection_probe_set_as_interior, RID, bool)
+	FUNC2(reflection_probe_set_enable_box_projection, RID, bool)
+	FUNC2(reflection_probe_set_enable_shadows, RID, bool)
+	FUNC2(reflection_probe_set_cull_mask, RID, uint32_t)
+
+	/* ROOM API */
+
+	FUNC0R(RID, room_create)
+	FUNC4(room_add_bounds, RID, const PoolVector<Vector2> &, float, const Transform &)
+	FUNC1(room_clear_bounds, RID)
+
+	/* PORTAL API */
+
+	// portals are only (x/y) points, forming a convex shape, which its clockwise
+	// order points outside. (z is 0);
+
+	FUNC0R(RID, portal_create)
+	FUNC2(portal_set_shape, RID, const Vector<Point2> &)
+	FUNC2(portal_set_enabled, RID, bool)
+	FUNC2(portal_set_disable_distance, RID, float)
+	FUNC2(portal_set_disabled_color, RID, const Color &)
+
+	/* BAKED LIGHT API */
+
+	FUNC0R(RID, gi_probe_create)
+
+	FUNC2(gi_probe_set_bounds, RID, const Rect3 &)
+	FUNC1RC(Rect3, gi_probe_get_bounds, RID)
+
+	FUNC2(gi_probe_set_cell_size, RID, float)
+	FUNC1RC(float, gi_probe_get_cell_size, RID)
+
+	FUNC2(gi_probe_set_to_cell_xform, RID, const Transform &)
+	FUNC1RC(Transform, gi_probe_get_to_cell_xform, RID)
+
+	FUNC2(gi_probe_set_dynamic_range, RID, int)
+	FUNC1RC(int, gi_probe_get_dynamic_range, RID)
+
+	FUNC2(gi_probe_set_energy, RID, float)
+	FUNC1RC(float, gi_probe_get_energy, RID)
+
+	FUNC2(gi_probe_set_bias, RID, float)
+	FUNC1RC(float, gi_probe_get_bias, RID)
+
+	FUNC2(gi_probe_set_propagation, RID, float)
+	FUNC1RC(float, gi_probe_get_propagation, RID)
+
+	FUNC2(gi_probe_set_interior, RID, bool)
+	FUNC1RC(bool, gi_probe_is_interior, RID)
+
+	FUNC2(gi_probe_set_compress, RID, bool)
+	FUNC1RC(bool, gi_probe_is_compressed, RID)
+
+	FUNC2(gi_probe_set_dynamic_data, RID, const PoolVector<int> &)
+	FUNC1RC(PoolVector<int>, gi_probe_get_dynamic_data, RID)
+
+	/* PARTICLES */
+
+	FUNC0R(RID, particles_create)
+
+	FUNC2(particles_set_emitting, RID, bool)
+	FUNC2(particles_set_amount, RID, int)
+	FUNC2(particles_set_lifetime, RID, float)
+	FUNC2(particles_set_pre_process_time, RID, float)
+	FUNC2(particles_set_explosiveness_ratio, RID, float)
+	FUNC2(particles_set_randomness_ratio, RID, float)
+	FUNC2(particles_set_custom_aabb, RID, const Rect3 &)
+	FUNC2(particles_set_speed_scale, RID, float)
+	FUNC2(particles_set_use_local_coordinates, RID, bool)
+	FUNC2(particles_set_process_material, RID, RID)
+	FUNC2(particles_set_fixed_fps, RID, int)
+	FUNC2(particles_set_fractional_delta, RID, bool)
+
+	FUNC2(particles_set_draw_order, RID, VS::ParticlesDrawOrder)
+
+	FUNC2(particles_set_draw_passes, RID, int)
+	FUNC3(particles_set_draw_pass_mesh, RID, int, RID)
+
+	FUNC1R(Rect3, particles_get_current_aabb, RID)
+
+	/* CAMERA API */
+
+	FUNC0R(RID, camera_create)
+	FUNC4(camera_set_perspective, RID, float, float, float)
+	FUNC4(camera_set_orthogonal, RID, float, float, float)
+	FUNC2(camera_set_transform, RID, const Transform &)
+	FUNC2(camera_set_cull_mask, RID, uint32_t)
+	FUNC2(camera_set_environment, RID, RID)
+	FUNC2(camera_set_use_vertical_aspect, RID, bool)
+
+	/* VIEWPORT TARGET API */
+
+	FUNC0R(RID, viewport_create)
+
+	FUNC3(viewport_set_size, RID, int, int)
+
+	FUNC2(viewport_set_active, RID, bool)
+	FUNC2(viewport_set_parent_viewport, RID, RID)
+
+	FUNC2(viewport_set_clear_mode, RID, ViewportClearMode)
+
+	FUNC3(viewport_attach_to_screen, RID, const Rect2 &, int)
+	FUNC1(viewport_detach, RID)
+
+	FUNC2(viewport_set_update_mode, RID, ViewportUpdateMode)
+	FUNC2(viewport_set_vflip, RID, bool)
+
+	FUNC1RC(RID, viewport_get_texture, RID)
+
+	FUNC2(viewport_set_hide_scenario, RID, bool)
+	FUNC2(viewport_set_hide_canvas, RID, bool)
+	FUNC2(viewport_set_disable_environment, RID, bool)
+	FUNC2(viewport_set_disable_3d, RID, bool)
+
+	FUNC2(viewport_attach_camera, RID, RID)
+	FUNC2(viewport_set_scenario, RID, RID)
+	FUNC2(viewport_attach_canvas, RID, RID)
+
+	FUNC2(viewport_remove_canvas, RID, RID)
+	FUNC3(viewport_set_canvas_transform, RID, RID, const Transform2D &)
+	FUNC2(viewport_set_transparent_background, RID, bool)
+
+	FUNC2(viewport_set_global_canvas_transform, RID, const Transform2D &)
+	FUNC3(viewport_set_canvas_layer, RID, RID, int)
+	FUNC2(viewport_set_shadow_atlas_size, RID, int)
+	FUNC3(viewport_set_shadow_atlas_quadrant_subdivision, RID, int, int)
+	FUNC2(viewport_set_msaa, RID, ViewportMSAA)
+	FUNC2(viewport_set_hdr, RID, bool)
+	FUNC2(viewport_set_usage, RID, ViewportUsage)
+
+	/* ENVIRONMENT API */
+
+	FUNC0R(RID, environment_create)
+
+	FUNC2(environment_set_background, RID, EnvironmentBG)
+	FUNC2(environment_set_sky, RID, RID)
+	FUNC2(environment_set_sky_scale, RID, float)
+	FUNC2(environment_set_bg_color, RID, const Color &)
+	FUNC2(environment_set_bg_energy, RID, float)
+	FUNC2(environment_set_canvas_max_layer, RID, int)
+	FUNC4(environment_set_ambient_light, RID, const Color &, float, float)
+	FUNC8(environment_set_ssr, RID, bool, int, float, float, float, bool, bool)
+	FUNC10(environment_set_ssao, RID, bool, float, float, float, float, float, float, const Color &, bool)
+
+	FUNC6(environment_set_dof_blur_near, RID, bool, float, float, float, EnvironmentDOFBlurQuality)
+	FUNC6(environment_set_dof_blur_far, RID, bool, float, float, float, EnvironmentDOFBlurQuality)
+	FUNC10(environment_set_glow, RID, bool, int, float, float, float, EnvironmentGlowBlendMode, float, float, bool)
+
+	FUNC9(environment_set_tonemap, RID, EnvironmentToneMapper, float, float, bool, float, float, float, float)
+
+	FUNC6(environment_set_adjustment, RID, bool, float, float, float, RID)
+
+	FUNC5(environment_set_fog, RID, bool, const Color &, const Color &, float)
+	FUNC6(environment_set_fog_depth, RID, bool, float, float, bool, float)
+	FUNC5(environment_set_fog_height, RID, bool, float, float, float)
+
+	FUNC0R(RID, scenario_create)
+
+	FUNC2(scenario_set_debug, RID, ScenarioDebugMode)
+	FUNC2(scenario_set_environment, RID, RID)
+	FUNC3(scenario_set_reflection_atlas_size, RID, int, int)
+	FUNC2(scenario_set_fallback_environment, RID, RID)
+
+	/* INSTANCING API */
+	// from can be mesh, light,  area and portal so far.
+	FUNC0R(RID, instance_create)
+
+	FUNC2(instance_set_base, RID, RID) // from can be mesh, light, poly, area and portal so far.
+	FUNC2(instance_set_scenario, RID, RID) // from can be mesh, light, poly, area and portal so far.
+	FUNC2(instance_set_layer_mask, RID, uint32_t)
+	FUNC2(instance_set_transform, RID, const Transform &)
+	FUNC2(instance_attach_object_instance_ID, RID, ObjectID)
+	FUNC3(instance_set_blend_shape_weight, RID, int, float)
+	FUNC3(instance_set_surface_material, RID, int, RID)
+	FUNC2(instance_set_visible, RID, bool)
+
+	FUNC2(instance_attach_skeleton, RID, RID)
+	FUNC2(instance_set_exterior, RID, bool)
+	FUNC2(instance_set_room, RID, RID)
+
+	FUNC2(instance_set_extra_visibility_margin, RID, real_t)
+
+	// don't use these in a game!
+	FUNC2RC(Vector<ObjectID>, instances_cull_aabb, const Rect3 &, RID)
+	FUNC3RC(Vector<ObjectID>, instances_cull_ray, const Vector3 &, const Vector3 &, RID)
+	FUNC2RC(Vector<ObjectID>, instances_cull_convex, const Vector<Plane> &, RID)
+
+	FUNC3(instance_geometry_set_flag, RID, InstanceFlags, bool)
+	FUNC2(instance_geometry_set_cast_shadows_setting, RID, ShadowCastingSetting)
+	FUNC2(instance_geometry_set_material_override, RID, RID)
+
+	FUNC5(instance_geometry_set_draw_range, RID, float, float, float, float)
+	FUNC2(instance_geometry_set_as_instance_lod, RID, RID)
+
+	/* CANVAS (2D) */
+
+	FUNC0R(RID, canvas_create)
+	FUNC3(canvas_set_item_mirroring, RID, RID, const Point2 &)
+	FUNC2(canvas_set_modulate, RID, const Color &)
+
+	FUNC0R(RID, canvas_item_create)
+	FUNC2(canvas_item_set_parent, RID, RID)
+
+	FUNC2(canvas_item_set_visible, RID, bool)
+	FUNC2(canvas_item_set_light_mask, RID, int)
+
+	FUNC2(canvas_item_set_transform, RID, const Transform2D &)
+	FUNC2(canvas_item_set_clip, RID, bool)
+	FUNC2(canvas_item_set_distance_field_mode, RID, bool)
+	FUNC3(canvas_item_set_custom_rect, RID, bool, const Rect2 &)
+	FUNC2(canvas_item_set_modulate, RID, const Color &)
+	FUNC2(canvas_item_set_self_modulate, RID, const Color &)
+
+	FUNC2(canvas_item_set_draw_behind_parent, RID, bool)
+
+	FUNC6(canvas_item_add_line, RID, const Point2 &, const Point2 &, const Color &, float, bool)
+	FUNC3(canvas_item_add_rect, RID, const Rect2 &, const Color &)
+	FUNC4(canvas_item_add_circle, RID, const Point2 &, float, const Color &)
+	FUNC6(canvas_item_add_texture_rect, RID, const Rect2 &, RID, bool, const Color &, bool)
+	FUNC6(canvas_item_add_texture_rect_region, RID, const Rect2 &, RID, const Rect2 &, const Color &, bool)
+	FUNC10(canvas_item_add_nine_patch, RID, const Rect2 &, const Rect2 &, RID, const Vector2 &, const Vector2 &, NinePatchAxisMode, NinePatchAxisMode, bool, const Color &)
+	FUNC6(canvas_item_add_primitive, RID, const Vector<Point2> &, const Vector<Color> &, const Vector<Point2> &, RID, float)
+	FUNC5(canvas_item_add_polygon, RID, const Vector<Point2> &, const Vector<Color> &, const Vector<Point2> &, RID)
+	FUNC7(canvas_item_add_triangle_array, RID, const Vector<int> &, const Vector<Point2> &, const Vector<Color> &, const Vector<Point2> &, RID, int)
+	FUNC3(canvas_item_add_mesh, RID, const RID &, RID)
+	FUNC3(canvas_item_add_multimesh, RID, RID, RID)
+	FUNC2(canvas_item_add_set_transform, RID, const Transform2D &)
+	FUNC2(canvas_item_add_clip_ignore, RID, bool)
+	FUNC2(canvas_item_set_sort_children_by_y, RID, bool)
+	FUNC2(canvas_item_set_z, RID, int)
+	FUNC2(canvas_item_set_z_as_relative_to_parent, RID, bool)
+	FUNC3(canvas_item_set_copy_to_backbuffer, RID, bool, const Rect2 &)
+
+	FUNC1(canvas_item_clear, RID)
+	FUNC2(canvas_item_set_draw_index, RID, int)
+
+	FUNC2(canvas_item_set_material, RID, RID)
+
+	FUNC2(canvas_item_set_use_parent_material, RID, bool)
+
+	FUNC0R(RID, canvas_light_create)
+	FUNC2(canvas_light_attach_to_canvas, RID, RID)
+	FUNC2(canvas_light_set_enabled, RID, bool)
+	FUNC2(canvas_light_set_scale, RID, float)
+	FUNC2(canvas_light_set_transform, RID, const Transform2D &)
+	FUNC2(canvas_light_set_texture, RID, RID)
+	FUNC2(canvas_light_set_texture_offset, RID, const Vector2 &)
+	FUNC2(canvas_light_set_color, RID, const Color &)
+	FUNC2(canvas_light_set_height, RID, float)
+	FUNC2(canvas_light_set_energy, RID, float)
+	FUNC3(canvas_light_set_z_range, RID, int, int)
+	FUNC3(canvas_light_set_layer_range, RID, int, int)
+	FUNC2(canvas_light_set_item_cull_mask, RID, int)
+	FUNC2(canvas_light_set_item_shadow_cull_mask, RID, int)
+
+	FUNC2(canvas_light_set_mode, RID, CanvasLightMode)
+
+	FUNC2(canvas_light_set_shadow_enabled, RID, bool)
+	FUNC2(canvas_light_set_shadow_buffer_size, RID, int)
+	FUNC2(canvas_light_set_shadow_gradient_length, RID, float)
+	FUNC2(canvas_light_set_shadow_filter, RID, CanvasLightShadowFilter)
+	FUNC2(canvas_light_set_shadow_color, RID, const Color &)
+
+	FUNC0R(RID, canvas_light_occluder_create)
+	FUNC2(canvas_light_occluder_attach_to_canvas, RID, RID)
+	FUNC2(canvas_light_occluder_set_enabled, RID, bool)
+	FUNC2(canvas_light_occluder_set_polygon, RID, RID)
+	FUNC2(canvas_light_occluder_set_transform, RID, const Transform2D &)
+	FUNC2(canvas_light_occluder_set_light_mask, RID, int)
+
+	FUNC0R(RID, canvas_occluder_polygon_create)
+	FUNC3(canvas_occluder_polygon_set_shape, RID, const PoolVector<Vector2> &, bool)
+	FUNC2(canvas_occluder_polygon_set_shape_as_lines, RID, const PoolVector<Vector2> &)
+
+	FUNC2(canvas_occluder_polygon_set_cull_mode, RID, CanvasOccluderPolygonCullMode)
+
+	/* CURSOR */
+	FUNC2(cursor_set_rotation, float, int) // radians
+	FUNC4(cursor_set_texture, RID, const Point2 &, int, const Rect2 &)
+	FUNC2(cursor_set_visible, bool, int)
+	FUNC2(cursor_set_pos, const Point2 &, int)
+
+	/* BLACK BARS */
+
+	FUNC4(black_bars_set_margins, int, int, int, int)
+	FUNC4(black_bars_set_images, RID, RID, RID, RID)
+
+	/* FREE */
+
+	FUNC1(free, RID)
+
+	/* EVENT QUEUING */
+
+	FUNC3(request_frame_drawn_callback, Object *, const StringName &, const Variant &)
+
+	virtual void init();
+	virtual void finish();
+	virtual void draw();
+	virtual void sync();
+	FUNC0RC(bool, has_changed)
+
+	/* RENDER INFO */
+
+	FUNC1R(int, get_render_info, RenderInfo)
+
+	FUNC3(set_boot_image, const Ref<Image> &, const Color &, bool)
+	FUNC1(set_default_clear_color, const Color &)
+
+	FUNC0R(RID, get_test_cube)
+
+	virtual bool has_feature(Features p_feature) const { return visual_server->has_feature(p_feature); }
+	virtual bool has_os_feature(const String &p_feature) const { return visual_server->has_os_feature(p_feature); }
+
+	VisualServerWrapMT(VisualServer *p_contained, bool p_create_thread);
+	~VisualServerWrapMT();
+
+#undef ServerName
+#undef ServerNameWrapMT
+#undef server_name
+};
+
+#ifdef DEBUG_SYNC
+#undef DEBUG_SYNC
+#endif
+#undef SYNC_DEBUG
+
+#endif

+ 11 - 1
servers/visual_server.h

@@ -579,7 +579,16 @@ public:
 	};
 	};
 
 
 	virtual void viewport_set_msaa(RID p_viewport, ViewportMSAA p_msaa) = 0;
 	virtual void viewport_set_msaa(RID p_viewport, ViewportMSAA p_msaa) = 0;
+
+	enum ViewportUsage {
+		VIEWPORT_USAGE_2D,
+		VIEWPORT_USAGE_2D_NO_SAMPLING,
+		VIEWPORT_USAGE_3D,
+		VIEWPORT_USAGE_3D_NO_EFFECTS,
+	};
+
 	virtual void viewport_set_hdr(RID p_viewport, bool p_enabled) = 0;
 	virtual void viewport_set_hdr(RID p_viewport, bool p_enabled) = 0;
+	virtual void viewport_set_usage(RID p_viewport, ViewportUsage p_usage) = 0;
 
 
 	/* ENVIRONMENT API */
 	/* ENVIRONMENT API */
 
 
@@ -623,7 +632,6 @@ public:
 		GLOW_BLEND_MODE_REPLACE,
 		GLOW_BLEND_MODE_REPLACE,
 	};
 	};
 	virtual void environment_set_glow(RID p_env, bool p_enable, int p_level_flags, float p_intensity, float p_strength, float p_bloom_treshold, EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_treshold, float p_hdr_bleed_scale, bool p_bicubic_upscale) = 0;
 	virtual void environment_set_glow(RID p_env, bool p_enable, int p_level_flags, float p_intensity, float p_strength, float p_bloom_treshold, EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_treshold, float p_hdr_bleed_scale, bool p_bicubic_upscale) = 0;
-	virtual void environment_set_fog(RID p_env, bool p_enable, float p_begin, float p_end, RID p_gradient_texture) = 0;
 
 
 	enum EnvironmentToneMapper {
 	enum EnvironmentToneMapper {
 		ENV_TONE_MAPPER_LINEAR,
 		ENV_TONE_MAPPER_LINEAR,
@@ -848,6 +856,8 @@ public:
 
 
 	virtual void free(RID p_rid) = 0; ///< free RIDs associated with the visual server
 	virtual void free(RID p_rid) = 0; ///< free RIDs associated with the visual server
 
 
+	virtual void request_frame_drawn_callback(Object *p_where, const StringName &p_method, const Variant &p_userdata) = 0;
+
 	/* EVENT QUEUING */
 	/* EVENT QUEUING */
 
 
 	virtual void draw() = 0;
 	virtual void draw() = 0;