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