Index: trunk/src/gl/gl_context.cc
===================================================================
--- trunk/src/gl/gl_context.cc	(revision 301)
+++ trunk/src/gl/gl_context.cc	(revision 302)
@@ -10,5 +10,4 @@
 #include "nv/gl/gl_device.hh"
 #include "nv/gl/gl_program.hh"
-#include "nv/gl/gl_vertex_buffer.hh"
 
 using namespace nv;
@@ -31,39 +30,39 @@
 }
 
-void nv::gl_context::bind( vertex_buffer* b )
-{
-	GLuint id = static_cast< gl_vertex_buffer* >( b )->glid;
-	glBindBuffer( GL_ARRAY_BUFFER, id );
-}
-
-void nv::gl_context::bind( index_buffer* b )
-{
-	GLuint id = static_cast< gl_index_buffer* >( b )->glid;
-	glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, id );
-}
-
-void nv::gl_context::bind( vertex_array* va )
-{
-	for ( vertex_buffer_attribute_map::iterator i = va->m_map.begin(); 	i != va->m_map.end(); ++i ) 
-	{
-		uint32 location             = static_cast<uint32>( i->first );
-		vertex_buffer_attribute* va = i->second;
-		vertex_buffer*           vb = va->get_buffer();
-		glEnableVertexAttribArray( location );
-		bind( vb );
-		glVertexAttribPointer( 
-			location, 
-			static_cast<GLint>( va->get_components() ), 
-			nv::datatype_to_gl_enum( va->get_datatype() ),
-			GL_FALSE,
-			static_cast<GLsizei>( va->get_stride() ),
-			(void*)va->get_offset()
-			);
-		unbind( vb );
-	}
-
-	if ( va->m_index )
-	{
-		bind( va->m_index );
+void nv::gl_context::bind( buffer b )
+{
+	const gl_buffer_info* info = static_cast< const gl_buffer_info* >( m_device->get_buffer_info( b ) );
+	if ( info )
+	{
+		glBindBuffer( buffer_type_to_enum( info->type ), info->glid );
+	}
+}
+
+void nv::gl_context::bind( vertex_array va )
+{
+	vertex_array_info* info = get_vertex_array_info( va );
+	if ( info )
+	{
+		for ( uint32 i = 0; i < info->count; ++i ) 
+		{
+			const vertex_buffer_attribute& vba = info->attr[i];
+			uint32 location                    = static_cast<uint32>( vba.location );
+			glEnableVertexAttribArray( location );
+			bind( vba.vbuffer );
+			glVertexAttribPointer( 
+				location, 
+				static_cast<GLint>( vba.components ), 
+				nv::datatype_to_gl_enum( vba.dtype ),
+				GL_FALSE,
+				static_cast<GLsizei>( vba.stride ),
+				(void*)vba.offset
+				);
+			unbind( vba.vbuffer );
+		}
+
+		if ( info->index.is_valid() )
+		{
+			bind( info->index );
+		}
 	}
 }
@@ -74,24 +73,27 @@
 }
 
-void nv::gl_context::unbind( vertex_buffer* )
-{
-	glBindBuffer( GL_ARRAY_BUFFER, 0 );
-}
-
-void nv::gl_context::unbind( index_buffer* )
-{
-	glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, 0 );
-}
-
-void nv::gl_context::unbind( vertex_array* va )
-{
-	if ( va->m_index )
-	{
-		unbind( va->m_index );
-	}
-
-	for ( vertex_buffer_attribute_map::iterator i = va->m_map.begin(); 	i != va->m_map.end(); ++i ) 
-	{
-		glDisableVertexAttribArray( static_cast<uint32>( i->first ) );
+void nv::gl_context::unbind( buffer b )
+{
+	const gl_buffer_info* info = static_cast< const gl_buffer_info* >( m_device->get_buffer_info( b ) );
+	if ( info )
+	{
+		glBindBuffer( buffer_type_to_enum( info->type ), 0 );
+	}
+}
+
+void nv::gl_context::unbind( vertex_array va )
+{
+	vertex_array_info* info = get_vertex_array_info( va );
+	if ( info )
+	{
+		if ( info->index.is_valid() )
+		{
+			unbind( info->index );
+		}
+
+		for ( uint32 i = 0; i < info->count; ++i ) 
+		{
+			glDisableVertexAttribArray( static_cast<uint32>( info->attr[i].location ) );
+		}
 	}
 }
@@ -110,14 +112,12 @@
 }
 
-void gl_context::update( vertex_buffer* b, const void* data, size_t offset, size_t size )
-{
-	bind( b );
-	glBufferSubData( GL_ARRAY_BUFFER, (GLintptr)offset, (GLsizeiptr)size, data );
-}
-
-void gl_context::update( index_buffer* b, const void* data, size_t offset, size_t size )
-{
-	bind( b );
-	glBufferSubData( GL_ELEMENT_ARRAY_BUFFER, (GLintptr)offset, (GLsizeiptr)size, data );
+void gl_context::update( buffer b, const void* data, size_t offset, size_t size )
+{
+	const gl_buffer_info* info = static_cast< const gl_buffer_info* >( m_device->get_buffer_info( b ) );
+	if ( info )
+	{
+		bind( b );
+		glBufferSubData( buffer_type_to_enum( info->type ), (GLintptr)offset, (GLsizeiptr)size, data );
+	}
 }
 
@@ -483,14 +483,15 @@
 }
 
-void gl_context::draw( primitive prim, const render_state& rs, program* p, vertex_array* va, size_t count )
+void gl_context::draw( primitive prim, const render_state& rs, program* p, vertex_array va, size_t count )
 {
 	apply_render_state( rs );
-	if ( count > 0 )
+	vertex_array_info* info = get_vertex_array_info( va );
+	if ( count > 0 && info )
 	{
 		bind( p );
 		bind( va );
-		if ( va->has_index_buffer() )
-		{
-			glDrawElements( primitive_to_enum(prim), static_cast<GLsizei>( count ), datatype_to_gl_enum( va->get_index_buffer_type() ), 0 );
+		if ( info->index.is_valid() )
+		{
+			glDrawElements( primitive_to_enum(prim), static_cast<GLsizei>( count ), datatype_to_gl_enum( info->index_type ), 0 );
 		}
 		else
Index: trunk/src/gl/gl_device.cc
===================================================================
--- trunk/src/gl/gl_device.cc	(revision 301)
+++ trunk/src/gl/gl_device.cc	(revision 302)
@@ -7,5 +7,4 @@
 #include "nv/gl/gl_window.hh"
 #include "nv/gl/gl_program.hh"
-#include "nv/gl/gl_vertex_buffer.hh"
 #include "nv/logging.hh"
 #include "nv/lib/sdl.hh"
@@ -56,19 +55,4 @@
 }
 
-vertex_buffer* gl_device::create_vertex_buffer( buffer_hint hint, size_t size, const void* source /*= nullptr */ )
-{
-	return new gl_vertex_buffer( hint, size, source );
-}
-
-index_buffer* gl_device::create_index_buffer( buffer_hint hint, size_t size, const void* source /*= nullptr */ )
-{
-	return new gl_index_buffer( hint, size, source );
-}
-
-vertex_array* gl_device::create_vertex_array()
-{
-	return new vertex_array();
-}
-
 // this is a temporary function that will be removed once we find a way to 
 // pass binary file data around
@@ -101,6 +85,8 @@
 gl_device::~gl_device()
 {
-	// TODO: better use release_texture
-	for ( auto& t : m_textures ) glDeleteTextures( 1, &t.glid );
+	while ( m_textures.size() > 0 )
+		release( m_textures.get_handle(0) );
+	while ( m_buffers.size() > 0 )
+		release( m_buffers.get_handle(0) );
 
 	SDL_Quit();
@@ -142,11 +128,27 @@
 }
 
-void nv::gl_device::release_texture( texture t )
+void nv::gl_device::release( texture t )
 {
 	gl_texture_info* info = m_textures.get( t );
 	if ( info )
 	{
-		glDeleteTextures( 1, &(info->glid) );
+		if ( info->glid != 0 )
+		{
+			glDeleteTextures( 1, &(info->glid) );
+		}
 		m_textures.destroy( t );
+	}
+}
+
+void nv::gl_device::release( buffer b )
+{
+	gl_buffer_info* info = m_buffers.get( b );
+	if ( info )
+	{
+		if ( info->glid != 0 )
+		{
+			glDeleteBuffers( 1, &(info->glid) );
+		}
+		m_buffers.destroy( b );
 	}
 }
@@ -157,2 +159,25 @@
 }
 
+nv::buffer nv::gl_device::create_buffer( buffer_type type, buffer_hint hint, size_t size, const void* source /*= nullptr */ )
+{
+	unsigned glid   = 0;
+	unsigned glenum = buffer_type_to_enum( type );
+	glGenBuffers( 1, &glid );
+
+	glBindBuffer( glenum, glid );
+	glBufferData( glenum, (GLsizeiptr)size, source, buffer_hint_to_enum( hint ) );
+	glBindBuffer( glenum, 0 );
+
+	buffer result = m_buffers.create();
+	gl_buffer_info* info = m_buffers.get( result );
+	info->type = type;
+	info->hint = hint;
+	info->size = size;
+	info->glid = glid;
+	return result;
+}
+
+const buffer_info* nv::gl_device::get_buffer_info( buffer t )
+{
+	return m_buffers.get( t );
+}
Index: trunk/src/gl/gl_enum.cc
===================================================================
--- trunk/src/gl/gl_enum.cc	(revision 301)
+++ trunk/src/gl/gl_enum.cc	(revision 302)
@@ -144,4 +144,14 @@
 	case DYNAMIC_DRAW  : return GL_DYNAMIC_DRAW;
 	NV_RETURN_COVERED_DEFAULT( 0 );
+	}
+}
+
+unsigned int nv::buffer_type_to_enum( buffer_type type )
+{
+	switch( type )
+	{
+	case VERTEX_BUFFER : return GL_ARRAY_BUFFER;
+	case INDEX_BUFFER  : return GL_ELEMENT_ARRAY_BUFFER;
+		NV_RETURN_COVERED_DEFAULT( 0 );
 	}
 }
Index: trunk/src/gl/gl_vertex_buffer.cc
===================================================================
--- trunk/src/gl/gl_vertex_buffer.cc	(revision 301)
+++ 	(revision )
@@ -1,45 +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_vertex_buffer.hh"
-
-#include "nv/lib/gl.hh"
-#include "nv/gl/gl_enum.hh"
-
-using namespace nv;
-
-gl_vertex_buffer::gl_vertex_buffer( buffer_hint hint, size_t size, const void* data ) 
-	: vertex_buffer( hint, size )
-{
-	glGenBuffers( 1, &glid );
-	glBindBuffer( GL_ARRAY_BUFFER, glid );
-	glBufferData( GL_ARRAY_BUFFER, (GLsizeiptr)m_size, data, buffer_hint_to_enum( m_hint ) );
-	glBindBuffer( GL_ARRAY_BUFFER, 0 );
-}
-
-nv::gl_vertex_buffer::~gl_vertex_buffer()
-{
-	if ( glid != 0 )
-	{
-		glDeleteBuffers( 1, &glid );
-	}
-}
-
-gl_index_buffer::gl_index_buffer( buffer_hint hint, size_t size, const void* data ) 
-	: index_buffer( hint, size )
-{
-	glGenBuffers( 1, &glid );
-
-	glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, glid );
-	glBufferData( GL_ELEMENT_ARRAY_BUFFER, (GLsizeiptr)m_size, data, buffer_hint_to_enum( m_hint ) );
-	glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, 0 );
-}
-
-nv::gl_index_buffer::~gl_index_buffer()
-{
-	if ( glid != 0 )
-	{
-		glDeleteBuffers( 1, &glid );
-	}
-}
