Index: trunk/src/engine/material_manager.cc
===================================================================
--- trunk/src/engine/material_manager.cc	(revision 500)
+++ trunk/src/engine/material_manager.cc	(revision 501)
@@ -20,5 +20,5 @@
 	uint8 data[2 * 2 * 3];
 	nv::raw_fill_n( data, 2 * 2 * 3, 0 );
-	m_default = m_context->get_device()->create_texture( ivec2(2,2), nv::image_format( nv::RGB ), nv::sampler(), data );
+	m_default = m_context->create_texture( ivec2(2,2), nv::image_format( nv::RGB ), nv::sampler(), data );
 }
 
@@ -34,5 +34,5 @@
 				if ( auto data = m_image_manager->get( mat->paths[i] ).lock() )
 				{
-					result->textures[i] = m_context->get_device()->create_texture( &*data, smp );
+					result->textures[i] = m_context->create_texture( &*data, smp );
 				}
 			}
@@ -53,5 +53,5 @@
 	for ( const texture& t : m->textures )
 	{
-		m_context->get_device()->release( t );
+		m_context->release( t );
 	}
 }
Index: trunk/src/engine/particle_engine.cc
===================================================================
--- trunk/src/engine/particle_engine.cc	(revision 500)
+++ trunk/src/engine/particle_engine.cc	(revision 501)
@@ -320,5 +320,5 @@
 
 	data.quota   = table.get<uint32>("quota", 1024 );
-	data.local   = table.get<bool>("local_space", false );
+//	data.local   = table.get<bool>("local_space", false );
 	data.accurate_facing = table.get<bool>("accurate_facing", false );
 	data.emmiter_count   = 0;
@@ -467,7 +467,6 @@
 {
 	m_context       = a_context;
-	m_device        = a_context->get_device();
-	m_program_local = m_device->create_program( nv_particle_engine_vertex_shader_local, nv_particle_engine_fragment_shader );
-	m_program_world = m_device->create_program( nv_particle_engine_vertex_shader_world, nv_particle_engine_fragment_shader );
+	m_program_local = m_context->create_program( nv_particle_engine_vertex_shader_local, nv_particle_engine_fragment_shader );
+	m_program_world = m_context->create_program( nv_particle_engine_vertex_shader_world, nv_particle_engine_fragment_shader );
 
 	register_standard_emmiters();
@@ -533,5 +532,5 @@
 	info->count = 0;
 	info->quota = max_particles;
-	info->vtx_buffer = m_device->create_buffer( VERTEX_BUFFER, STREAM_DRAW, info->quota * sizeof( particle_quad )/*, info->quads_[0].data*/ );
+	info->vtx_buffer = m_context->create_buffer( VERTEX_BUFFER, STREAM_DRAW, info->quota * sizeof( particle_quad )/*, info->quads_[0].data*/ );
 	vertex_array_desc desc;
 	desc.add_vertex_buffers< particle_vtx >( info->vtx_buffer, true );
@@ -545,6 +544,6 @@
 {
 	clear();
-	m_device->release( m_program_world );
-	m_device->release( m_program_local );
+	m_context->release( m_program_world );
+	m_context->release( m_program_local );
 }
 
@@ -785,5 +784,5 @@
 	vec3 source;
 	mat3 orient;
-	bool local = info->data->local;
+//	bool local = info->data->local;
 // 	if ( !local ) 
 // 	{
Index: trunk/src/engine/program_manager.cc
===================================================================
--- trunk/src/engine/program_manager.cc	(revision 500)
+++ trunk/src/engine/program_manager.cc	(revision 501)
@@ -36,5 +36,5 @@
 	}
 
-	add( id, m_context->get_device()->create_program( vsource, fsource ) );
+	add( id, m_context->create_program( vsource, fsource ) );
 	return true;
 }
@@ -42,5 +42,5 @@
 void nv::program_manager::release( program p )
 {
-	m_context->get_device()->release( p );
+	m_context->release( p );
 }
 
Index: trunk/src/gfx/debug_draw.cc
===================================================================
--- trunk/src/gfx/debug_draw.cc	(revision 500)
+++ trunk/src/gfx/debug_draw.cc	(revision 501)
@@ -35,5 +35,5 @@
 	: m_context( a_context ), m_program(), m_va()
 {
-	m_program = m_context->get_device()->create_program( nv_debug_draw_vertex_shader, nv_debug_draw_fragment_shader );
+	m_program = m_context->create_program( nv_debug_draw_vertex_shader, nv_debug_draw_fragment_shader );
 	m_buffer_size = 0;
 }
@@ -45,5 +45,5 @@
 		if ( m_va.is_valid() ) m_context->release( m_va );
 		m_buffer_size = nv::max( m_data.size(), 4096U, m_buffer_size );
-		m_vb = m_context->get_device()->create_buffer( VERTEX_BUFFER, nv::STREAM_DRAW, m_buffer_size * sizeof( debug_vtx ) );
+		m_vb = m_context->create_buffer( VERTEX_BUFFER, nv::STREAM_DRAW, m_buffer_size * sizeof( debug_vtx ) );
 		vertex_array_desc va_desc;
 		va_desc.add_vertex_buffers< debug_vtx >( m_vb, true );
@@ -89,4 +89,4 @@
 {
 	m_context->release( m_va );
-	m_context->get_device()->release( m_program );
+	m_context->release( m_program );
 }
Index: trunk/src/gl/gl_context.cc
===================================================================
--- trunk/src/gl/gl_context.cc	(revision 500)
+++ trunk/src/gl/gl_context.cc	(revision 501)
@@ -66,5 +66,4 @@
 		}
 	}
-	glBindBuffer( GL_ARRAY_BUFFER, 0 );
 	glBindVertexArray( 0 );
 
@@ -104,7 +103,7 @@
 		{
 			if ( info->attr[i].owner ) 
-				m_device->release( info->attr[i].vbuffer );
-		}
-		if ( info->index.is_valid() && info->index_owner) m_device->release( info->index );
+				release( info->attr[i].vbuffer );
+		}
+		if ( info->index.is_valid() && info->index_owner) release( info->index );
 		glDeleteVertexArrays( 1, &info->glid );
 		m_vertex_arrays.destroy( va );
@@ -223,6 +222,4 @@
 		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 );
@@ -270,4 +267,5 @@
 }
 
+
 void nv::gl_context::bind( buffer b, texture t )
 {
@@ -304,4 +302,5 @@
 			set_active_texture( slot );
 			glBindTexture( texture_type_to_enum( info->type ), info->glid );
+			m_bound_textures[slot] = t;
 		}
 	}
@@ -314,5 +313,6 @@
 	if ( info )
 	{
-		glUseProgram( info->glid );
+		if ( m_bound_program != p )
+			glUseProgram( info->glid );
 		gdevice->update_uniforms( info );
 		if ( !info->validated )
@@ -320,4 +320,5 @@
 			validate_program( p );
 		}
+		m_bound_program = p;
 	}
 }
@@ -369,5 +370,7 @@
 void nv::gl_context::unbind( program )
 {
-	glUseProgram( 0 );
+	if ( m_bound_program )
+		glUseProgram( 0 );
+	m_bound_program = program();
 }
 
@@ -375,5 +378,8 @@
 {
 	if ( slot != m_active_slot )
+	{
 		glActiveTexture( GL_TEXTURE0 + static_cast<GLenum>( slot ) );
+		m_active_slot = slot;
+	}
 }
 
@@ -419,11 +425,11 @@
 		unsigned     gl_type = texture_type_to_enum( info->type );
 
-		if ( m_bound_textures[ m_active_slot ] != t )
-			glBindTexture( gl_type, info->glid );
-		int this_should_be_subTexImage;
+		bind( t, texture_slot::TEXTURE_0 );
 		if ( info->type == TEXTURE_3D || info->type == TEXTURE_2D_ARRAY )
-			glTexImage3D( gl_type, 0, static_cast<GLint>( nv::image_format_to_internal_enum( format.format ) ), size.x, size.y, size.z, 0, nv::image_format_to_enum( format.format ), nv::datatype_to_gl_enum( format.type ), data );
+//			glTexImage3D( gl_type, 0, static_cast<GLint>( nv::image_format_to_internal_enum( format.format ) ), size.x, size.y, size.z, 0, nv::image_format_to_enum( format.format ), nv::datatype_to_gl_enum( format.type ), data );
+			glTexSubImage3D( gl_type, 0, 0, 0, 0, size.x, size.y, size.z, nv::image_format_to_enum( format.format ), nv::datatype_to_gl_enum( format.type ), data );
 		else
-			glTexImage2D( gl_type, 0, static_cast<GLint>( nv::image_format_to_internal_enum(format.format) ), size.x, size.y, 0, nv::image_format_to_enum(format.format), nv::datatype_to_gl_enum(format.type), data );
+//			glTexImage2D( gl_type, 0, static_cast<GLint>( nv::image_format_to_internal_enum(format.format) ), size.x, size.y, 0, nv::image_format_to_enum(format.format), nv::datatype_to_gl_enum(format.type), data );
+			glTexSubImage2D( gl_type, 0, 0, 0, size.x, size.y, nv::image_format_to_enum( format.format ), nv::datatype_to_gl_enum( format.type ), data );
 	}
 }
@@ -518,7 +524,10 @@
 void gl_context::set_viewport( const ivec4& viewport )
 {
-	NV_ASSERT_ALWAYS( viewport.z > 0 && viewport.w > 0, "viewport dimensions must be greater than zero!" );
-	m_viewport = viewport;
-	glViewport( viewport.x, viewport.y, viewport.z, viewport.w );
+	if ( m_viewport != viewport )
+	{
+		NV_ASSERT_ALWAYS( viewport.z > 0 && viewport.w > 0, "viewport dimensions must be greater than zero!" );
+		m_viewport = viewport;
+		glViewport( viewport.x, viewport.y, viewport.z, viewport.w );
+	}
 }
 
@@ -860,4 +869,144 @@
 }
 
+nv::texture nv::gl_context::create_texture( texture_type type, ivec2 size, image_format aformat, sampler asampler, const void* data /*= nullptr */ )
+{
+	texture result = create_texture( type, aformat.format );
+	gl_texture_info* info = static_cast<gl_device*>( m_device )->get_full_texture_info( result );
+	bind( result, texture_slot::TEXTURE_0 );
+	unsigned glid = info->glid;
+	unsigned gl_type = texture_type_to_enum( type );
+	GLenum gl_internal = GLenum( image_format_to_internal_enum( aformat.format ) );
+	unsigned gl_enum = image_format_to_enum( aformat.format );
+
+	bool is_depth = aformat.format == DEPTH16 || aformat.format == DEPTH24 || aformat.format == DEPTH32;
+
+	// Detect if mipmapping was requested
+	// 	if ( gl_type == GL_TEXTURE_2D && gl_enum != GL_RED_INTEGER && asampler.filter_min != sampler::LINEAR && asampler.filter_min != sampler::NEAREST )
+	// 	{
+	// 		// TODO: This should not be done if we use framebuffers!
+	// 		glTexParameteri( gl_type, GL_GENERATE_MIPMAP, GL_TRUE);
+	// 	}
+
+	if ( asampler.filter_max != sampler::NEAREST )
+	{
+		asampler.filter_max = sampler::LINEAR;
+	}
+
+	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_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 ) ) );
+		glTexParameteri( gl_type, GL_TEXTURE_WRAP_T, GLint( nv::sampler_wrap_to_enum( asampler.wrap_t ) ) );
+	}
+
+	if ( is_depth )
+	{
+		//		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
+		glTexParameteri( gl_type, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE );
+		glTexParameteri( gl_type, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL );
+	}
+
+	// #define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE
+	// #define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF
+	// 
+	// 	float aniso = 0.0f;
+	// 	glGetFloatv( GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &aniso );
+	// 	NV_LOG_INFO( "Anisotropy at ", aniso, " (", int( aniso ), " ) " );
+	// 	glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, aniso );
+
+	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 );
+
+	if ( gl_type == GL_TEXTURE_2D && gl_enum != GL_RED_INTEGER && asampler.filter_min != sampler::LINEAR && asampler.filter_min != sampler::NEAREST )
+	{
+		// TODO: This should not be done if we use framebuffers!
+		glGenerateMipmap( gl_type );
+	}
+
+	bind( texture(), texture_slot::TEXTURE_0 );
+
+	info->type = type;
+	info->format = aformat;
+	info->tsampler = asampler;
+	info->size = ivec3( size.x, size.y, 1 );
+	info->glid = glid;
+
+	return result;
+}
+
+nv::texture nv::gl_context::create_texture( texture_type type, ivec3 size, image_format aformat, sampler asampler, const void* data /*= nullptr */ )
+{
+	texture result = create_texture( type, aformat.format );
+	gl_texture_info* info = static_cast<gl_device*>( m_device )->get_full_texture_info( result );
+	bind( result, texture_slot::TEXTURE_0 );
+	unsigned glid = info->glid;
+
+	unsigned gl_type = texture_type_to_enum( type );
+
+	bool is_depth = aformat.format == DEPTH16 || aformat.format == DEPTH24 || aformat.format == DEPTH32;
+
+	if ( asampler.filter_max != sampler::NEAREST )
+	{
+		asampler.filter_max = sampler::LINEAR;
+	}
+
+	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 ) ) );
+	glTexParameteri( gl_type, GL_TEXTURE_WRAP_S, GLint( nv::sampler_wrap_to_enum( asampler.wrap_s ) ) );
+	glTexParameteri( gl_type, GL_TEXTURE_WRAP_T, GLint( nv::sampler_wrap_to_enum( asampler.wrap_t ) ) );
+
+	if ( is_depth )
+	{
+		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
+		glTexParameteri( gl_type, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE );
+		glTexParameteri( gl_type, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL );
+	}
+
+	//glTexStorage3D( GL_TEXTURE_2D_ARRAY, mipLevelCount, GL_RGBA8, width, height, layerCount );
+	glTexImage3D( gl_type, 0, GLint( nv::image_format_to_internal_enum( aformat.format ) ), size.x, size.y, size.z, 0, nv::image_format_to_enum( aformat.format ), nv::datatype_to_gl_enum( aformat.type ), data );
+
+	bind( texture(), texture_slot::TEXTURE_0 );
+
+	info->type = type;
+	info->format = aformat;
+	info->tsampler = asampler;
+	info->size = size;
+	info->glid = glid;
+
+	return result;
+}
+
+nv::buffer nv::gl_context::create_buffer( buffer_type type, buffer_hint hint, size_t size, const void* source /*= nullptr */ )
+{
+	buffer result = static_cast<gl_device*>( m_device )->create_buffer( type, hint );
+	if ( size > 0 ) create_buffer( result, size, source );
+	return result;
+}
+
+void nv::gl_context::create_buffer( buffer b, size_t size, const void* source /*= nullptr */ )
+{
+	gl_buffer_info* info = static_cast<gl_device*>( m_device )->get_full_buffer_info( b );
+	if ( info )
+	{
+		unsigned glenum = buffer_type_to_enum( info->type );
+		glBindBuffer( glenum, info->glid );
+		glBufferData( glenum, GLsizeiptr( size ), source, buffer_hint_to_enum( info->hint ) );
+		glBindBuffer( glenum, 0 );
+	}
+}
+
 void nv::gl_context::set_draw_buffers( uint32 count, const output_slot* slots )
 {
Index: trunk/src/gl/gl_device.cc
===================================================================
--- trunk/src/gl/gl_device.cc	(revision 500)
+++ trunk/src/gl/gl_device.cc	(revision 501)
@@ -94,88 +94,6 @@
 }
 
-nv::texture nv::gl_device::create_texture( texture_type type, ivec2 size, image_format aformat, sampler asampler, const void* data /*= nullptr */ )
-{
-	NV_ASSERT_ALWAYS( type != TEXTURE_1D_BUFFER && type != TEXTURE_3D && type != TEXTURE_2D_ARRAY, "2D texture type expected!" );
-	unsigned glid = 0;
-	unsigned gl_type = texture_type_to_enum( type );
-	GLenum gl_internal = GLenum( nv::image_format_to_internal_enum( aformat.format ) );
-	unsigned gl_enum = nv::image_format_to_enum( aformat.format );
-
-	bool is_depth = aformat.format == DEPTH16 || aformat.format == DEPTH24 || aformat.format == DEPTH32;
-
-	glGenTextures( 1, &glid );
-
-	glBindTexture( gl_type, glid );
-
-	// Detect if mipmapping was requested
-// 	if ( gl_type == GL_TEXTURE_2D && gl_enum != GL_RED_INTEGER && asampler.filter_min != sampler::LINEAR && asampler.filter_min != sampler::NEAREST )
-// 	{
-// 		// TODO: This should not be done if we use framebuffers!
-// 		glTexParameteri( gl_type, GL_GENERATE_MIPMAP, GL_TRUE);
-// 	}
-
-	if ( asampler.filter_max != sampler::NEAREST )
-	{
-		asampler.filter_max = sampler::LINEAR;
-	}
-
-	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_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 ) ) );
-		glTexParameteri( gl_type, GL_TEXTURE_WRAP_T, GLint( nv::sampler_wrap_to_enum( asampler.wrap_t ) ) );
-	}
-
-	if ( is_depth )
-	{
-//		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
-		glTexParameteri( gl_type, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE );
-		glTexParameteri( gl_type, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL );
-	}
-
-// #define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE
-// #define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF
-// 
-// 	float aniso = 0.0f;
-// 	glGetFloatv( GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &aniso );
-// 	NV_LOG_INFO( "Anisotropy at ", aniso, " (", int( aniso ), " ) " );
-// 	glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, aniso );
-
-	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 );
-
-	if ( gl_type == GL_TEXTURE_2D && gl_enum != GL_RED_INTEGER && asampler.filter_min != sampler::LINEAR && asampler.filter_min != sampler::NEAREST )
-	{
-		// TODO: This should not be done if we use framebuffers!
-		glGenerateMipmap( gl_type );
-	}
-
-
-	glBindTexture( gl_type, 0 );
-
-	texture result = m_textures.create();
-	gl_texture_info* info = m_textures.get( result );
-	info->type     = type;
-	info->format   = aformat;
-	info->tsampler = asampler;
-	info->size     = ivec3( size.x, size.y, 1 );
-	info->glid     = glid;
-	return result;
-}
-
-
 nv::texture nv::gl_device::create_texture( texture_type type, pixel_format format )
 {
-	NV_ASSERT_ALWAYS( type == TEXTURE_1D_BUFFER, "create_texture not texture buffer!" );
 	unsigned glid = 0;
 
@@ -193,51 +111,4 @@
 }
 
-nv::texture nv::gl_device::create_texture( texture_type type, ivec3 size, image_format aformat, sampler asampler, const void* data /*= nullptr */ )
-{
-	NV_ASSERT_ALWAYS( type == TEXTURE_3D || type == TEXTURE_2D_ARRAY, "3D texture type expected!" );
-	unsigned glid = 0;
-	unsigned gl_type = texture_type_to_enum( type );
-
-	bool is_depth = aformat.format == DEPTH16 || aformat.format == DEPTH24 || aformat.format == DEPTH32;
-
-	glGenTextures( 1, &glid );
-	glBindTexture( gl_type, glid );
-
-	if ( asampler.filter_max != sampler::NEAREST )
-	{
-		asampler.filter_max = sampler::LINEAR;
-	}
-
-	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 ) ) );
-	glTexParameteri( gl_type, GL_TEXTURE_WRAP_S, GLint( nv::sampler_wrap_to_enum( asampler.wrap_s ) ) );
-	glTexParameteri( gl_type, GL_TEXTURE_WRAP_T, GLint( nv::sampler_wrap_to_enum( asampler.wrap_t ) ) );
-
-	if ( is_depth )
-	{
-		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
-		glTexParameteri( gl_type, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE );
-		glTexParameteri( gl_type, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL );
-	}
-
-	//glTexStorage3D( GL_TEXTURE_2D_ARRAY, mipLevelCount, GL_RGBA8, width, height, layerCount );
-	glTexImage3D( gl_type, 0, GLint( nv::image_format_to_internal_enum( aformat.format ) ), size.x, size.y, size.z, 0, nv::image_format_to_enum( aformat.format ), nv::datatype_to_gl_enum( aformat.type ), data );
-	glBindTexture( gl_type, 0 );
-
-	texture result = m_textures.create();
-	gl_texture_info* info = m_textures.get( result );
-	info->type = type;
-	info->format = aformat;
-	info->tsampler = asampler;
-	info->size = size;
-	info->glid = glid;
-	return result;
-}
-
-
-
 void nv::gl_device::release( texture t )
 {
@@ -271,16 +142,9 @@
 }
 
-nv::buffer nv::gl_device::create_buffer( buffer_type type, buffer_hint hint, size_t size, const void* source /*= nullptr */ )
+nv::buffer nv::gl_device::create_buffer( buffer_type type, buffer_hint hint )
 {
 	unsigned glid = 0;
 	unsigned glenum = buffer_type_to_enum( type );
 	glGenBuffers( 1, &glid );
-
-	if ( size > 0 )
-	{
-		glBindBuffer( glenum, glid );
-		glBufferData( glenum, GLsizeiptr( size ), source, buffer_hint_to_enum( hint ) );
-		glBindBuffer( glenum, 0 );
-	}
 
 	buffer result = m_buffers.create();
@@ -288,19 +152,7 @@
 	info->type = type;
 	info->hint = hint;
-	info->size = size;
+	info->size = 0;
 	info->glid = glid;
 	return result;
-}
-
-void nv::gl_device::create_buffer( buffer b, size_t size, const void* source )
-{
-	gl_buffer_info* info = m_buffers.get( b );
-	if ( info )
-	{
-		unsigned glenum = buffer_type_to_enum( info->type );
-		glBindBuffer( glenum, info->glid );
-		glBufferData( glenum, GLsizeiptr( size ), source, buffer_hint_to_enum( info->hint ) );
-		glBindBuffer( glenum, 0 );
-	}
 }
 
@@ -330,4 +182,15 @@
 		m_programs.destroy( p );
 	}
+}
+
+nv::gl_texture_info* nv::gl_device::get_full_texture_info( texture t )
+{
+	return m_textures.get( t );
+
+}
+
+nv::gl_buffer_info* nv::gl_device::get_full_buffer_info( buffer t )
+{
+	return m_buffers.get( t );
 }
 
Index: trunk/src/gui/gui_gfx_renderer.cc
===================================================================
--- trunk/src/gui/gui_gfx_renderer.cc	(revision 500)
+++ trunk/src/gui/gui_gfx_renderer.cc	(revision 501)
@@ -116,5 +116,5 @@
 	~screen_render_data()
 	{
-		ctx->get_device()->release( shader );
+		ctx->release( shader );
 		ctx->release( varray );
 	}
@@ -157,5 +157,5 @@
 	screen_render_data* sr = new screen_render_data( w->get_context(), 1024 );
 	m_render_data = sr;
-	sr->shader = m_window->get_device()->create_program( nv_gui_vertex_shader, nv_gui_fragment_shader );
+	sr->shader = m_window->get_context()->create_program( nv_gui_vertex_shader, nv_gui_fragment_shader );
 	m_scene_state.get_camera().set_ortho( 0.0f, float( m_window->get_width() ), float( m_window->get_height() ), 0.0f );
 
@@ -166,5 +166,5 @@
 
 	nv::sampler sampler( nv::sampler::LINEAR, nv::sampler::CLAMP_TO_EDGE );
-	sr->tex = m_window->get_device()->create_texture( m_atlas.get_size(), image_format( nv::RGBA, nv::UBYTE ), sampler, nullptr );
+	sr->tex = m_window->get_context()->create_texture( m_atlas.get_size(), image_format( nv::RGBA, nv::UBYTE ), sampler, nullptr );
 
 	m_render_state.depth_test.enabled = false;
@@ -395,5 +395,5 @@
 	if ( m_render_data )
 	{
-		m_context->get_device()->release( reinterpret_cast< screen_render_data* >( m_render_data )->tex );
+		m_context->release( reinterpret_cast< screen_render_data* >( m_render_data )->tex );
 		delete m_render_data;
 	}
Index: trunk/src/lib/gl.cc
===================================================================
--- trunk/src/lib/gl.cc	(revision 500)
+++ trunk/src/lib/gl.cc	(revision 501)
@@ -55,28 +55,28 @@
 
 
-static void* load_gl_ext_symbol_impl( const nv::string_view& name, nv::log_level fail_level = nv::LOG_DEBUG )
-{
-	void* result = gl_ext_loader( name.data() );
-	NV_LOG( ( result ? nv::LOG_DEBUG : fail_level ), "load_gl_ext_symbol : ", name, ( result ? " succeded." : "failed." ) );
-	return result;
-}
-
-static void* load_gl_ext_symbol( const nv::string_view& name, bool iterate, const nv::string_view& ext )
-{
-	void * result        = nullptr;
-	nv::string128 test_name = name + ext;
-	result = load_gl_ext_symbol_impl( !ext.empty() ? test_name : name );
-	if ( result ) return result;
-	if ( iterate )
-	{
-		test_name = name + "ARB"_ls;
-		result = gl_ext_loader( test_name.data() );
-		if ( result ) return result;
-		test_name = name + "EXT"_ls;
-		result = gl_ext_loader( test_name.data() );
-		if ( result ) return result;
-	}
-	return result;
-}
+// static void* load_gl_ext_symbol_impl( const nv::string_view& name, nv::log_level fail_level = nv::LOG_DEBUG )
+// {
+// 	void* result = gl_ext_loader( name.data() );
+// 	NV_LOG( ( result ? nv::LOG_DEBUG : fail_level ), "load_gl_ext_symbol : ", name, ( result ? " succeded." : "failed." ) );
+// 	return result;
+// }
+
+// static void* load_gl_ext_symbol( const nv::string_view& name, bool iterate, const nv::string_view& ext )
+// {
+// 	void * result        = nullptr;
+// 	nv::string128 test_name = name + ext;
+// 	result = load_gl_ext_symbol_impl( !ext.empty() ? test_name : name );
+// 	if ( result ) return result;
+// 	if ( iterate )
+// 	{
+// 		test_name = name + "ARB"_ls;
+// 		result = gl_ext_loader( test_name.data() );
+// 		if ( result ) return result;
+// 		test_name = name + "EXT"_ls;
+// 		result = gl_ext_loader( test_name.data() );
+// 		if ( result ) return result;
+// 	}
+// 	return result;
+// }
 
 bool nv::load_gl_library( const char* path, bool force_reload )
