Index: trunk/src/gl/gl_context.cc
===================================================================
--- trunk/src/gl/gl_context.cc	(revision 311)
+++ trunk/src/gl/gl_context.cc	(revision 313)
@@ -12,4 +12,71 @@
 using namespace nv;
 
+nv::vertex_array nv::gl_context::create_vertex_array()
+{
+	vertex_array result = m_vertex_arrays.create();
+	vertex_array_info* info = m_vertex_arrays.get( result );
+	info->count       = 0;
+	info->index       = buffer();
+	info->index_owner = false;
+	info->index_type  = USHORT;
+	return result;
+}
+
+nv::framebuffer nv::gl_context::create_framebuffer()
+{
+	if ( is_gl_extension_loaded( GL_EXT_FRAMEBUFFER_OBJECT ) )
+	{
+		unsigned glid   = 0;
+		glGenFramebuffers( 1, &glid );
+		framebuffer result = m_framebuffers.create();
+		gl_framebuffer_info* info = m_framebuffers.get( result );
+		info->glid = glid;
+		info->color_attachment_count = 0;
+		return result;
+	}
+	else return framebuffer();
+}
+
+void nv::gl_context::release( vertex_array va )
+{
+	vertex_array_info* info = m_vertex_arrays.get( va );
+	if ( info )
+	{
+		for ( uint32 i = 0; i < info->count; ++i )
+		{
+			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 );
+		m_vertex_arrays.destroy( va );
+	}
+}
+
+void nv::gl_context::release( framebuffer f )
+{
+	gl_framebuffer_info* info = m_framebuffers.get( f );
+	if ( info )
+	{
+		// TODO: release textures?
+		glBindFramebuffer(GL_FRAMEBUFFER, 0);
+		glDeleteFramebuffers(1, &info->glid);
+	}
+}
+
+const vertex_array_info* nv::gl_context::get_vertex_array_info( vertex_array va ) const 
+{
+	return m_vertex_arrays.get( va );
+}
+
+const framebuffer_info* nv::gl_context::get_framebuffer_info( framebuffer f ) const
+{
+	return m_framebuffers.get( f );
+}
+
+vertex_array_info* nv::gl_context::get_vertex_array_info_mutable( vertex_array va ) 
+{
+	return m_vertex_arrays.get( va );
+}
+
+
 void gl_context::bind( texture t, texture_slot slot )
 {
@@ -32,16 +99,16 @@
 }
 
-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( 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 )
 {
-	const vertex_array_info* info = m_device->get_vertex_array_info( va );
+	const vertex_array_info* info = m_vertex_arrays.get( va );
 	if ( info )
 	{
@@ -51,5 +118,12 @@
 			uint32 location                    = static_cast<uint32>( vba.location );
 			glEnableVertexAttribArray( location );
-			bind( vba.vbuffer );
+			const gl_buffer_info* vinfo = static_cast< const gl_buffer_info* >( m_device->get_buffer_info( vba.vbuffer ) );
+			if ( vinfo && vinfo->type == VERTEX_BUFFER )
+				glBindBuffer( GL_ARRAY_BUFFER, vinfo->glid );
+			else
+			{
+				// TODO: report error
+			}
+
 			glVertexAttribPointer( 
 				location, 
@@ -60,11 +134,28 @@
 				(void*)vba.offset
 				);
-			unbind( vba.vbuffer );
-		}
+		}
+		glBindBuffer( GL_ARRAY_BUFFER, 0 );
 
 		if ( info->index.is_valid() )
 		{
-			bind( info->index );
-		}
+			const gl_buffer_info* iinfo = static_cast< const gl_buffer_info* >( m_device->get_buffer_info( info->index ) );
+			if ( iinfo && iinfo->type == INDEX_BUFFER )
+			{
+				glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, iinfo->glid );
+			}
+			else
+			{
+				// TODO: report error
+			}
+		}
+	}
+}
+
+void nv::gl_context::bind( framebuffer f )
+{
+	const gl_framebuffer_info* info = m_framebuffers.get( f );
+	if ( info )
+	{
+		glBindFramebuffer( GL_FRAMEBUFFER, info->glid );
 	}
 }
@@ -75,21 +166,21 @@
 }
 
-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( 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 )
 {
-	const vertex_array_info* info = m_device->get_vertex_array_info( va );
+	const vertex_array_info* info = m_vertex_arrays.get( va );
 	if ( info )
 	{
 		if ( info->index.is_valid() )
 		{
-			unbind( info->index );
+			glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, 0 );
 		}
 
@@ -98,4 +189,14 @@
 			glDisableVertexAttribArray( static_cast<uint32>( info->attr[i].location ) );
 		}
+	}
+}
+
+void nv::gl_context::unbind( framebuffer f )
+{
+	// this way we are sure that the extension is loaded
+	const gl_framebuffer_info* info = m_framebuffers.get( f );
+	if ( info )
+	{
+		glBindFramebuffer( GL_FRAMEBUFFER, 0 );
 	}
 }
@@ -119,6 +220,7 @@
 	if ( info )
 	{
-		bind( b );
-		glBufferSubData( buffer_type_to_enum( info->type ), (GLintptr)offset, (GLsizeiptr)size, data );
+		GLenum glenum = buffer_type_to_enum( info->type );
+		glBindBuffer( glenum, info->glid );
+		glBufferSubData( glenum, (GLintptr)offset, (GLsizeiptr)size, data );
 	}
 }
@@ -483,4 +585,8 @@
 nv::gl_context::~gl_context()
 {
+	while ( m_framebuffers.size() > 0 )
+		release( m_framebuffers.get_handle(0) );
+	while ( m_vertex_arrays.size() > 0 )
+		release( m_vertex_arrays.get_handle(0) );
 }
 
@@ -500,5 +606,5 @@
 {
 	apply_render_state( rs );
-	const vertex_array_info* info = m_device->get_vertex_array_info( va );
+	const vertex_array_info* info = m_vertex_arrays.get( va );
 	if ( count > 0 && info )
 	{
