Index: trunk/src/gl/gl_context.cc
===================================================================
--- trunk/src/gl/gl_context.cc	(revision 491)
+++ trunk/src/gl/gl_context.cc	(revision 492)
@@ -74,8 +74,8 @@
 	}
 
-	for ( uint32 i = 0; i < info->count; ++i )
-	{
-		glDisableVertexAttribArray( static_cast<uint32>( info->attr[i].location ) );
-	}
+// 	for ( uint32 i = 0; i < info->count; ++i )
+// 	{
+// 		glDisableVertexAttribArray( static_cast<uint32>( info->attr[i].location ) );
+// 	}
 
 
@@ -83,5 +83,5 @@
 }
 
-nv::framebuffer nv::gl_context::create_framebuffer()
+nv::framebuffer nv::gl_context::create_framebuffer( uint32 temp_samples )
 {
 	unsigned glid   = 0;
@@ -92,4 +92,5 @@
 	info->depth_rb_glid = 0;
 	info->color_attachment_count = 0;
+	info->sample_count = temp_samples;
 	return result;
 }
@@ -192,5 +193,8 @@
 		glGenRenderbuffers( 1, &(info->depth_rb_glid) );
 		glBindRenderbuffer( GL_RENDERBUFFER, info->depth_rb_glid );
-		glRenderbufferStorage( GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, size.x, size.y );
+		if ( info->sample_count > 1 )
+			glRenderbufferStorageMultisample( GL_RENDERBUFFER, info->sample_count, GL_DEPTH_COMPONENT16, size.x, size.y );
+		else
+			glRenderbufferStorage( GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, size.x, size.y );
 		glFramebufferRenderbuffer( GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, info->depth_rb_glid );
 		glBindRenderbuffer( GL_RENDERBUFFER, 0 );
@@ -211,4 +215,21 @@
 
 
+void nv::gl_context::blit( framebuffer from, framebuffer to, clear_state::buffers_type mask, ivec2 src1, ivec2 src2, ivec2 dst1, ivec2 dst2 )
+{
+	gl_framebuffer_info* finfo = m_framebuffers.get( from );
+	gl_framebuffer_info* tinfo = m_framebuffers.get( to );
+	if ( finfo )
+	{
+		glBindFramebuffer( GL_READ_FRAMEBUFFER, finfo->glid );
+		glBindFramebuffer( GL_DRAW_FRAMEBUFFER, tinfo ? tinfo->glid : 0 );
+		unsigned filter = mask == clear_state::COLOR_BUFFER ? GL_LINEAR : GL_NEAREST;
+		int remove_below;
+		filter = GL_NEAREST;
+		glBlitFramebuffer( src1.x, src1.y, src2.x, src2.y, dst1.x, dst1.y, dst2.x, dst2.y, clear_state_buffers_to_mask( mask ), filter );
+		glBindFramebuffer( GL_READ_FRAMEBUFFER, 0 );
+		if ( tinfo ) glBindFramebuffer( GL_DRAW_FRAMEBUFFER, 0 );
+	}
+}
+
 bool nv::gl_context::check( framebuffer_slot ft )
 {
@@ -220,4 +241,7 @@
 	switch ( result )
 	{
+	case GL_FRAMEBUFFER_UNDEFINED                     : NV_LOG_ERROR( "gl_context::check : Framebuffer undefined!" ); break;
+	case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE        : NV_LOG_ERROR( "gl_context::check : Incomplete multisample!" ); break;
+	case GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS      : NV_LOG_ERROR( "gl_context::check : Incomplete layer targets!" ); break;
 	case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT         : NV_LOG_ERROR( "gl_context::check : Framebuffer incomplete attachment!" ); break;
 	case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT : NV_LOG_ERROR( "gl_context::check : Framebuffer missing attachment!" ); break;
@@ -255,8 +279,6 @@
 	{
 		NV_ASSERT_ALWAYS( binfo->type == TEXTURE_BUFFER && tinfo->type == TEXTURE_1D_BUFFER, "bad texture or buffer type!" );
-		glActiveTexture( GL_TEXTURE0 );
-		glBindTexture( GL_TEXTURE_BUFFER, tinfo->glid );
+		bind( t, TEXTURE_0 );
 		glTexBuffer( GL_TEXTURE_BUFFER, image_format_to_internal_enum( tinfo->format.format ), binfo->glid );
-		glBindTexture( GL_TEXTURE_BUFFER, 0 );
 	}
 }
@@ -276,9 +298,12 @@
 void gl_context::bind( texture t, texture_slot slot )
 {
-	const gl_texture_info* info = static_cast< const gl_texture_info* >( m_device->get_texture_info( t ) );
-	if ( info )
-	{
-		glActiveTexture( GL_TEXTURE0 + static_cast< GLenum >( slot ) );
-		glBindTexture( texture_type_to_enum( info->type ), info->glid );
+	if ( m_bound_textures[ slot ] != t )
+	{
+		const gl_texture_info* info = static_cast< const gl_texture_info* >( m_device->get_texture_info( t ) );
+		if ( info )
+		{
+			set_active_texture( slot );
+			glBindTexture( texture_type_to_enum( info->type ), info->glid );
+		}
 	}
 }
@@ -318,4 +343,10 @@
 }
 
+void nv::gl_context::set_active_texture( texture_slot slot )
+{
+	if ( slot != m_active_slot )
+		glActiveTexture( GL_TEXTURE0 + static_cast<GLenum>( slot ) );
+}
+
 // void nv::gl_context::unbind( buffer b )
 // {
@@ -352,4 +383,5 @@
 	const gl_texture_info* info = static_cast< const gl_texture_info* >( m_device->get_texture_info( t ) );
 	NV_ASSERT_ALWAYS( info->type != TEXTURE_1D_BUFFER, "Buffer texture passed to update!" );
+	NV_ASSERT_ALWAYS( info->type != TEXTURE_2D_MULTISAMPLE, "Multisample texture passed to update!" );
 	if ( info )
 	{
@@ -358,5 +390,6 @@
 		unsigned     gl_type = texture_type_to_enum( info->type );
 
-		glBindTexture( gl_type, info->glid );
+		if ( m_bound_textures[ m_active_slot ] != t )
+			glBindTexture( gl_type, info->glid );
 		int this_should_be_subTexImage;
 		if ( info->type == TEXTURE_3D || info->type == TEXTURE_2D_ARRAY )
@@ -543,4 +576,13 @@
 		glDepthMask( mask );
 		m_render_state.depth_mask = mask;
+	}
+}
+
+void gl_context::apply_multisample( bool multisample )
+{
+	if ( m_render_state.multisample != multisample )
+	{
+		glDepthMask( multisample );
+		m_render_state.multisample = multisample;
 	}
 }
@@ -727,4 +769,5 @@
 	apply_color_mask( state.color_mask );
 	apply_depth_mask( state.depth_mask );
+	apply_multisample( state.multisample );
 	apply_polygon_mode( state.polygon_mode );
 }
@@ -736,4 +779,5 @@
 	// TODO: configurable:
 //	load_gl_extensions( GL_EXT_FRAMEBUFFER_BLIT | GL_EXT_FRAMEBUFFER_OBJECT | GL_EXT_TEXTURE_ARRAY );
+	m_active_slot = texture_slot( -1 );
 	force_apply_render_state( m_render_state );
 }
Index: trunk/src/gl/gl_device.cc
===================================================================
--- trunk/src/gl/gl_device.cc	(revision 491)
+++ trunk/src/gl/gl_device.cc	(revision 492)
@@ -98,5 +98,5 @@
 	unsigned glid = 0;
 	unsigned gl_type = texture_type_to_enum( type );
-	GLint gl_internal = GLint( nv::image_format_to_internal_enum( aformat.format ) );
+	GLenum gl_internal = GLenum( nv::image_format_to_internal_enum( aformat.format ) );
 	unsigned gl_enum = nv::image_format_to_enum( aformat.format );
 
@@ -119,8 +119,11 @@
 	}
 
-	glTexParameteri( gl_type, GL_TEXTURE_MIN_FILTER, GLint( nv::sampler_filter_to_enum( asampler.filter_min ) ) );
-	glTexParameteri( gl_type, GL_TEXTURE_MAG_FILTER, GLint( nv::sampler_filter_to_enum( asampler.filter_max ) ) );
+	if ( gl_type != GL_TEXTURE_2D_MULTISAMPLE )
+	{
+		glTexParameteri( gl_type, GL_TEXTURE_MIN_FILTER, GLint( nv::sampler_filter_to_enum( asampler.filter_min ) ) );
+		glTexParameteri( gl_type, GL_TEXTURE_MAG_FILTER, GLint( nv::sampler_filter_to_enum( asampler.filter_max ) ) );
+	}
 	
-	if ( gl_enum != GL_RED_INTEGER )
+	if ( gl_type != GL_TEXTURE_2D_MULTISAMPLE && gl_enum != GL_RED_INTEGER )
 	{
 		glTexParameteri( gl_type, GL_TEXTURE_WRAP_S, GLint( nv::sampler_wrap_to_enum( asampler.wrap_s ) ) );
@@ -130,6 +133,6 @@
 	if ( is_depth )
 	{
-		glTexParameteri( gl_type, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
-		glTexParameteri( gl_type, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
+//		glTexParameteri( gl_type, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
+//		glTexParameteri( gl_type, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
 
 		// This is to allow usage of shadow2DProj function in the shader
@@ -146,5 +149,8 @@
 // 	glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, aniso );
 
-	glTexImage2D( gl_type, 0, gl_internal, size.x, size.y, 0, gl_enum, nv::datatype_to_gl_enum(aformat.type), data );
+	if ( gl_type != GL_TEXTURE_2D_MULTISAMPLE )
+		glTexImage2D( gl_type, 0, gl_internal, size.x, size.y, 0, gl_enum, nv::datatype_to_gl_enum(aformat.type), data );
+	else
+		glTexImage2DMultisample( gl_type, 4, gl_internal, size.x, size.y, 1 );
 
 	glBindTexture( gl_type, 0 );
@@ -163,7 +169,6 @@
 nv::texture nv::gl_device::create_texture( texture_type type, pixel_format format )
 {
-	NV_ASSERT_ALWAYS( type == TEXTURE_1D_BUFFER );
+	NV_ASSERT_ALWAYS( type == TEXTURE_1D_BUFFER, "create_texture not texture buffer!" );
 	unsigned glid = 0;
-	unsigned gl_type = texture_type_to_enum( type );
 
 	glGenTextures( 1, &glid );
@@ -552,4 +557,6 @@
 		NV_ASSERT( u, "Unknown uniform type!" );
 		(*p->m_uniform_map)[ name ] = u;
+		//NV_LOG_DEBUG( "Uniform : ", name, " - ", utype, "/", uni_len );
+
 	}
 
Index: trunk/src/gl/gl_enum.cc
===================================================================
--- trunk/src/gl/gl_enum.cc	(revision 491)
+++ trunk/src/gl/gl_enum.cc	(revision 492)
@@ -15,12 +15,13 @@
 	switch( type )
 	{
-	case TEXTURE_1D       : return GL_TEXTURE_1D;
-	case TEXTURE_2D       : return GL_TEXTURE_2D;
-	case TEXTURE_RECT     : return GL_TEXTURE_RECTANGLE;
-	case TEXTURE_3D       : return GL_TEXTURE_3D;
-	case TEXTURE_CUBE     : return GL_TEXTURE_CUBE_MAP;
- 	case TEXTURE_1D_ARRAY : return GL_TEXTURE_1D_ARRAY;
- 	case TEXTURE_2D_ARRAY : return GL_TEXTURE_2D_ARRAY;
-	case TEXTURE_1D_BUFFER: return GL_TEXTURE_BUFFER;
+	case TEXTURE_1D             : return GL_TEXTURE_1D;
+	case TEXTURE_2D             : return GL_TEXTURE_2D;
+	case TEXTURE_RECT           : return GL_TEXTURE_RECTANGLE;
+	case TEXTURE_3D             : return GL_TEXTURE_3D;
+	case TEXTURE_CUBE           : return GL_TEXTURE_CUBE_MAP;
+ 	case TEXTURE_1D_ARRAY       : return GL_TEXTURE_1D_ARRAY;
+ 	case TEXTURE_2D_ARRAY       : return GL_TEXTURE_2D_ARRAY;
+	case TEXTURE_1D_BUFFER      : return GL_TEXTURE_BUFFER;
+	case TEXTURE_2D_MULTISAMPLE : return GL_TEXTURE_2D_MULTISAMPLE;
 	NV_RETURN_COVERED_DEFAULT( 0 );
 	}
Index: trunk/src/gui/gui_environment.cc
===================================================================
--- trunk/src/gui/gui_environment.cc	(revision 491)
+++ trunk/src/gui/gui_environment.cc	(revision 492)
@@ -182,4 +182,7 @@
 		{ 
 			handle h = get_element( position( ev.mbutton.x, ev.mbutton.y ) );
+			element* e = m_elements.get( h );
+			if ( e->m_on_click ) e->m_on_click();
+
 			set_selected( h );
 			return true;
@@ -312,4 +315,13 @@
 }
 
+void nv::gui::environment::set_on_click( handle e, const function< void() >& on_click )
+{
+	element* ep = m_elements.get( e );
+	if ( ep != nullptr )
+	{
+		ep->m_on_click = on_click;
+	}
+}
+
 void nv::gui::environment::set_text( handle e, const string_twine& text )
 {
Index: trunk/src/gui/gui_gfx_renderer.cc
===================================================================
--- trunk/src/gui/gui_gfx_renderer.cc	(revision 491)
+++ trunk/src/gui/gui_gfx_renderer.cc	(revision 492)
@@ -249,6 +249,6 @@
 		const char* stext[] = { "", "selected", "hover" };
 		const char* selector = stext[border];
-		if ( e->m_flags[HOVER] )    selector = stext[2];
-		if ( e->m_flags[SELECTED] ) selector = stext[1];
+		if ( e->m_flags[HOVER] && e->m_flags[DIRTY_HOVER] )    selector = stext[2];
+		if ( e->m_flags[SELECTED] && e->m_flags[DIRTY_SELECT] ) selector = stext[1];
 
 		if ( m_style.get( e, "skin", selector, path ) )
Index: trunk/src/lib/gl.cc
===================================================================
--- trunk/src/lib/gl.cc	(revision 491)
+++ trunk/src/lib/gl.cc	(revision 492)
@@ -26,5 +26,5 @@
 #define NV_GL_FUN_REN( rtype, fname, rname, fparams ) rtype (NV_GL_APIENTRY *rname) fparams = nullptr;
 #define NV_GL_FUN_EXT NV_GL_FUN
-#include <nv/lib/detail/gl_core/gl_functions_3_1.inc>
+#include <nv/lib/detail/gl_core/gl_functions_3_2.inc>
 #if NV_PLATFORM == NV_WINDOWS
 #include <nv/lib/detail/wgl_functions.inc>
@@ -106,5 +106,5 @@
 #	define NV_GL_FUN( rtype, fname, fparams ) NV_GL_LOAD( fname )
 #	define NV_GL_FUN_EXT( rtype, fname, fparams ) NV_GL_LOAD_EXT( fname )
-#	include <nv/lib/detail/gl_core/gl_functions_3_1.inc>
+#	include <nv/lib/detail/gl_core/gl_functions_3_2.inc>
 #	undef NV_GL_FUN_EXT
 #	undef NV_GL_FUN
Index: trunk/src/sdl/sdl_window.cc
===================================================================
--- trunk/src/sdl/sdl_window.cc	(revision 491)
+++ trunk/src/sdl/sdl_window.cc	(revision 492)
@@ -30,6 +30,6 @@
 	//	SDL_GL_SetAttribute( SDL_GL_MULTISAMPLESAMPLES, 4 );
 
- 	SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
- 	SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
+ 	SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4);
+ 	SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
 
 	SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE );
