Index: trunk/src/gl/gl_context.cc
===================================================================
--- trunk/src/gl/gl_context.cc	(revision 300)
+++ trunk/src/gl/gl_context.cc	(revision 301)
@@ -8,5 +8,5 @@
 #include "nv/lib/gl.hh"
 #include "nv/lib/sdl.hh"
-#include "nv/gl/gl_texture2d.hh"
+#include "nv/gl/gl_device.hh"
 #include "nv/gl/gl_program.hh"
 #include "nv/gl/gl_vertex_buffer.hh"
@@ -14,9 +14,12 @@
 using namespace nv;
 
-void gl_context::bind( texture2d* texture, texture_slot slot )
-{
-	GLuint id = static_cast< gl_texture2d* >( texture )->glid;
-	glActiveTexture( GL_TEXTURE0 + static_cast< GLenum >( slot ) );
-	glBindTexture( GL_TEXTURE_2D, id );
+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( GL_TEXTURE_2D, info->glid );
+	}
 }
 
@@ -94,12 +97,15 @@
 }
 
-void gl_context::update( texture2d* texture, void* data )
-{
-	GLuint id = static_cast< gl_texture2d* >( texture )->glid;
-	image_format format = texture->get_format();
-	ivec2        size   = texture->get_size();
-
-	glBindTexture( GL_TEXTURE_2D, id );
-	glTexImage2D( GL_TEXTURE_2D, 0, (GLint)nv::image_format_to_enum(format.format), size.x, size.y, 0, nv::image_format_to_enum(format.format), nv::datatype_to_gl_enum(format.type), data );
+void nv::gl_context::update( texture t, void* data )
+{
+	const gl_texture_info* info = static_cast< const gl_texture_info* >( m_device->get_texture_info( t ) );
+	if ( info )
+	{
+		image_format format = info->format;
+		ivec2        size   = info->size;
+
+		glBindTexture( GL_TEXTURE_2D, info->glid );
+		glTexImage2D( GL_TEXTURE_2D, 0, (GLint)nv::image_format_to_enum(format.format), size.x, size.y, 0, nv::image_format_to_enum(format.format), nv::datatype_to_gl_enum(format.type), data );
+	}
 }
 
Index: trunk/src/gl/gl_device.cc
===================================================================
--- trunk/src/gl/gl_device.cc	(revision 300)
+++ trunk/src/gl/gl_device.cc	(revision 301)
@@ -8,8 +8,9 @@
 #include "nv/gl/gl_program.hh"
 #include "nv/gl/gl_vertex_buffer.hh"
-#include "nv/gl/gl_texture2d.hh"
 #include "nv/logging.hh"
 #include "nv/lib/sdl.hh"
 #include "nv/lib/sdl_image.hh"
+#include "nv/gl/gl_enum.hh"
+#include "nv/lib/gl.hh"
 
 using namespace nv;
@@ -88,9 +89,4 @@
 }
 
-texture2d* gl_device::create_texture2d( ivec2 size, pixel_format aformat, datatype adatatype, sampler asampler, void* data /*= nullptr */ )
-{
-	return new gl_texture2d( size, aformat, adatatype, asampler, data );
-}
-
 uint32 gl_device::get_ticks()
 {
@@ -105,4 +101,58 @@
 gl_device::~gl_device()
 {
+	// TODO: better use release_texture
+	for ( auto& t : m_textures ) glDeleteTextures( 1, &t.glid );
+
 	SDL_Quit();
 }
+
+nv::texture nv::gl_device::create_texture( ivec2 size, image_format aformat, sampler asampler, void* data /*= nullptr */ )
+{
+	unsigned glid = 0;
+	glGenTextures( 1, &glid );
+
+	glBindTexture( GL_TEXTURE_2D, glid );
+
+	// Detect if mipmapping was requested
+	if (( asampler.filter_min != sampler::LINEAR && asampler.filter_min != sampler::NEAREST ) ||
+		( asampler.filter_max != sampler::LINEAR && asampler.filter_max != sampler::NEAREST ))
+	{
+		glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);
+	}
+
+	glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, (int)nv::sampler_filter_to_enum( asampler.filter_min ) );
+	glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, (int)nv::sampler_filter_to_enum( asampler.filter_max ) );
+	glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, (int)nv::sampler_wrap_to_enum( asampler.wrap_s) );
+	glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, (int)nv::sampler_wrap_to_enum( asampler.wrap_t) );
+
+	if (data)
+	{
+		glTexImage2D( GL_TEXTURE_2D, 0, (GLint)nv::image_format_to_enum(aformat.format), size.x, size.y, 0, nv::image_format_to_enum(aformat.format), nv::datatype_to_gl_enum(aformat.type), data );
+	}
+
+	glBindTexture( GL_TEXTURE_2D, 0 );
+
+	texture result = m_textures.create();
+	gl_texture_info* info = m_textures.get( result );
+	info->format  = aformat;
+	info->sampler = asampler;
+	info->size    = size;
+	info->glid    = glid;
+	return result;
+}
+
+void nv::gl_device::release_texture( texture t )
+{
+	gl_texture_info* info = m_textures.get( t );
+	if ( info )
+	{
+		glDeleteTextures( 1, &(info->glid) );
+		m_textures.destroy( t );
+	}
+}
+
+const texture_info* nv::gl_device::get_texture_info( texture t )
+{
+	return m_textures.get( t );
+}
+
Index: trunk/src/gl/gl_texture2d.cc
===================================================================
--- trunk/src/gl/gl_texture2d.cc	(revision 300)
+++ 	(revision )
@@ -1,46 +1,0 @@
-// Copyright (C) 2012-2013 Kornel Kisielewicz
-// This file is part of NV Libraries.
-// For conditions of distribution and use, see copyright notice in nv.hh
-
-#include "nv/gl/gl_texture2d.hh"
-
-#include "nv/gl/gl_enum.hh"
-#include "nv/lib/gl.hh"
-
-using namespace nv;
-
-nv::gl_texture2d::gl_texture2d( ivec2 size, pixel_format aformat, datatype adatatype, sampler asampler, void* data /*= nullptr */ )
-	: texture2d( size, aformat, adatatype, asampler )
-{
-	glGenTextures( 1, &glid );
-
-	glBindTexture( GL_TEXTURE_2D, glid );
-
-	// Detect if mipmapping was requested
-	if (( asampler.filter_min != sampler::LINEAR && asampler.filter_min != sampler::NEAREST ) ||
-		( asampler.filter_max != sampler::LINEAR && asampler.filter_max != sampler::NEAREST ))
-	{
-		glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);
-	}
-
-	glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, (int)nv::sampler_filter_to_enum( m_sampler.filter_min ) );
-	glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, (int)nv::sampler_filter_to_enum( m_sampler.filter_max ) );
-	glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, (int)nv::sampler_wrap_to_enum( m_sampler.wrap_s) );
-	glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, (int)nv::sampler_wrap_to_enum( m_sampler.wrap_t) );
-
-	if (data)
-	{
-		glTexImage2D( GL_TEXTURE_2D, 0, (GLint)nv::image_format_to_enum(m_format.format), m_size.x, m_size.y, 0, nv::image_format_to_enum(m_format.format), nv::datatype_to_gl_enum(m_format.type), data );
-	}
-
-	glBindTexture( GL_TEXTURE_2D, 0 );
-}
-
-nv::gl_texture2d::~gl_texture2d()
-{
-	if ( glid != 0 )
-	{
-		glDeleteTextures( 1, &glid );
-	}
-}
-
Index: trunk/src/gui/gui_renderer.cc
===================================================================
--- trunk/src/gui/gui_renderer.cc	(revision 300)
+++ trunk/src/gui/gui_renderer.cc	(revision 301)
@@ -65,6 +65,6 @@
 {
 public:
-	screen_render_data( context* ctx, size_t initial_size )
-		: buffer( ctx, nv::DYNAMIC_DRAW, initial_size ), varray( nullptr ), shader(nullptr), texture(nullptr) 
+	screen_render_data( context* actx, size_t initial_size )
+		: buffer( actx, nv::DYNAMIC_DRAW, initial_size ), varray( nullptr ), shader(nullptr)
 	{
 
@@ -74,11 +74,10 @@
 		delete shader; 
 		delete varray; 
-		delete texture;
 	}
 
 	nv::sliced_buffer<gui_quad> buffer;
+	nv::texture       tex;
 	nv::vertex_array* varray;
 	nv::program*      shader;
-	nv::texture2d*    texture;
 };
 
@@ -121,5 +120,5 @@
 
 	nv::sampler sampler( nv::sampler::LINEAR, nv::sampler::CLAMP_TO_EDGE );
-	sr->texture = m_window->get_device()->create_texture2d( m_atlas.get_size(), nv::RGBA, nv::UBYTE, sampler, nullptr );
+	sr->tex = m_window->get_device()->create_texture( m_atlas.get_size(), image_format( nv::RGBA, nv::UBYTE ), sampler, nullptr );
 
 	m_render_state.depth_test.enabled = false;
@@ -262,5 +261,5 @@
 	if ( m_reupload )
 	{
-		m_context->update( sr->texture, (void*)m_atlas.get_data() );
+		m_context->update( sr->tex, (void*)m_atlas.get_data() );
 		m_reupload = false;
 	}
@@ -273,5 +272,5 @@
 		sr->varray->update_vertex_buffer( nv::slot::COLOR,    vb, false );
 	}
-	m_context->bind( sr->texture, TEX_DIFFUSE );
+	m_context->bind( sr->tex, TEX_DIFFUSE );
 	m_context->draw( TRIANGLES, m_render_state, m_scene_state, sr->shader, sr->varray, sr->buffer.get_size() * 6 );
 }
@@ -283,4 +282,8 @@
 		delete p;
 	}
-	delete m_render_data;
-}
+	if ( m_render_data )
+	{
+		m_context->get_device()->release_texture( ((screen_render_data*)m_render_data)->tex );
+		delete m_render_data;
+	}
+}
