Index: trunk/src/gl/gl_context.cc
===================================================================
--- trunk/src/gl/gl_context.cc	(revision 37)
+++ trunk/src/gl/gl_context.cc	(revision 37)
@@ -0,0 +1,348 @@
+// 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_context.hh"
+
+#include "nv/gl/gl_enum.hh"
+#include "nv/lib/gl.hh"
+
+using namespace nv;
+
+void gl_context::clear( const clear_state& cs )
+{
+	// apply_framebuffer
+	apply_scissor_test( cs.scissor_test );
+	apply_color_mask( cs.color_mask );
+	apply_depth_mask( cs.depth_mask );
+	// stencil_mask_separate
+
+	if ( m_clear_color != cs.color )
+	{
+		glClearColor( cs.color.r, cs.color.g, cs.color.b, cs.color.a );
+		m_clear_color = cs.color;
+	}
+
+	if ( m_clear_depth != cs.depth )
+	{
+		glClearDepth( cs.depth );
+		m_clear_depth = cs.depth;
+	}
+
+	if ( m_clear_stencil != cs.stencil )
+	{
+		glClearStencil( cs.stencil );
+		m_clear_stencil = cs.stencil;
+	}
+
+	glClear( cs.buffers );
+}
+
+const ivec4& gl_context::get_viewport()
+{
+	return m_viewport;
+}
+
+void gl_context::set_viewport( const ivec4& viewport )
+{
+	if ( viewport.z < 0 || viewport.w < 0 )
+	{
+		throw new logic_error("viewport width and height must be greater than zero!");
+	}
+
+	m_viewport = viewport;
+	glViewport( viewport.x, viewport.y, viewport.z, viewport.w );
+}
+
+void gl_context::enable( unsigned int what, bool value )
+{
+	if ( value )
+	{
+		glEnable( what );
+	}
+	else
+	{
+		glDisable( what );
+	}
+}
+
+void gl_context::apply_stencil_test( const stencil_test& stencil )
+{
+	if ( m_render_state.stencil_test.enabled != stencil.enabled )
+	{
+		enable( GL_STENCIL_TEST, stencil.enabled );
+		m_render_state.stencil_test.enabled = stencil.enabled;
+	}
+
+	if ( stencil.enabled )
+	{
+		apply_stencil_face( GL_FRONT, m_render_state.stencil_test.front_face, stencil.front_face );
+		apply_stencil_face( GL_BACK,  m_render_state.stencil_test.back_face,  stencil.back_face );
+	}
+}
+
+void gl_context::apply_stencil_face( int face, stencil_test_face& stencil, const stencil_test_face& new_stencil )
+{
+	if (( stencil.op_fail       != new_stencil.op_fail       ) ||
+		( stencil.op_depth_fail != new_stencil.op_depth_fail ) ||
+		( stencil.op_depth_pass != new_stencil.op_depth_pass ) )
+	{
+		glStencilOpSeparate( face,
+			stencil_operation_to_enum( new_stencil.op_fail ),
+			stencil_operation_to_enum( new_stencil.op_depth_fail ),
+			stencil_operation_to_enum( new_stencil.op_depth_pass )
+		);
+
+		stencil.op_fail       = new_stencil.op_fail;
+		stencil.op_depth_fail = new_stencil.op_depth_fail;
+		stencil.op_depth_pass = new_stencil.op_depth_pass;
+	}
+
+	if (( stencil.function  != new_stencil.function ) ||
+		( stencil.ref_value != new_stencil.ref_value ) ||
+		( stencil.mask      != new_stencil.mask ))
+	{
+		glStencilFuncSeparate( face,
+			stencil_function_to_enum( new_stencil.function ),
+			new_stencil.ref_value,
+			new_stencil.mask
+		);
+
+		stencil.function  = new_stencil.function;
+		stencil.ref_value = new_stencil.ref_value;
+		stencil.mask      = new_stencil.mask;
+	}
+}
+
+void gl_context::apply_scissor_test( const scissor_test& scissor )
+{
+	if ( m_render_state.scissor_test.enabled != scissor.enabled )
+	{
+		enable( GL_SCISSOR_TEST, scissor.enabled );
+		m_render_state.scissor_test.enabled = scissor.enabled;
+	}
+
+	if ( scissor.dim.x < 0 || scissor.dim.y < 0 )
+	{
+		throw new logic_error("scissor_test.rect width and height must be greater than zero!");
+	}
+
+	if ( scissor.enabled )
+	{
+		if ( m_render_state.scissor_test.dim != scissor.dim || m_render_state.scissor_test.pos != scissor.pos )
+		{
+			glScissor( 
+				scissor.pos.x, scissor.pos.y, 
+				scissor.dim.x, scissor.dim.y
+			);
+			m_render_state.scissor_test.dim = scissor.dim;
+			m_render_state.scissor_test.pos = scissor.pos;
+		}
+	}
+}
+
+void gl_context::apply_depth_test( const depth_test& depth )
+{
+	if ( m_render_state.depth_test.enabled != depth.enabled )
+	{
+		enable( GL_DEPTH_TEST, depth.enabled );
+		m_render_state.depth_test.enabled = depth.enabled;
+	}
+
+	if ( depth.enabled )
+	{
+		if ( m_render_state.depth_test.function != depth.function )
+		{
+			glDepthFunc( depth_state_function_to_enum( depth.function ) );
+			m_render_state.depth_test.function = depth.function;
+		}
+	}
+}
+
+void gl_context::apply_depth_mask( bool mask )
+{
+	if ( m_render_state.depth_mask != mask )
+	{
+		glDepthMask( mask );
+		m_render_state.depth_mask = mask;
+	}
+}
+
+void gl_context::apply_depth_range( const depth_range& range )
+{
+	if ( range.near < 0.0 || range.near > 1.0 )
+	{
+		throw new logic_error("render_state.depth_range.near must be between zero and one!");
+	}
+	if ( range.far < 0.0 || range.far > 1.0 )
+	{
+		throw new logic_error("render_state.depth_range.far must be between zero and one!");
+	}
+
+	if ((m_render_state.depth_range.far  != range.far) ||
+		(m_render_state.depth_range.near != range.near))
+	{
+		glDepthRange( range.near, range.far );
+
+		m_render_state.depth_range.far  = range.far;
+		m_render_state.depth_range.near = range.near;
+	}
+}
+
+void gl_context::apply_color_mask( const color_mask& mask )
+{
+	if ( m_render_state.color_mask != mask )
+	{
+		glColorMask( mask.red, mask.green, mask.blue, mask.alpha );
+		m_render_state.color_mask = mask;
+	}
+}
+
+void gl_context::apply_blending( const blending& blend )
+{
+	if ( m_render_state.blending.enabled != blend.enabled )
+	{
+		enable( GL_BLEND, blend.enabled );
+		m_render_state.blending.enabled = blend.enabled;
+	}
+
+	if ( blend.enabled )
+	{
+		if ((m_render_state.blending.src_rgb_factor   != blend.src_rgb_factor ) ||
+			(m_render_state.blending.dst_rgb_factor   != blend.dst_rgb_factor ) ||
+			(m_render_state.blending.src_alpha_factor != blend.src_alpha_factor ) ||
+			(m_render_state.blending.dst_alpha_factor != blend.dst_alpha_factor ))
+		{
+			glBlendFuncSeparate(
+				blending_factor_to_enum( blend.src_rgb_factor ),
+				blending_factor_to_enum( blend.dst_rgb_factor ),
+				blending_factor_to_enum( blend.src_alpha_factor ),
+				blending_factor_to_enum( blend.dst_alpha_factor )
+			);
+
+			m_render_state.blending.src_rgb_factor   = blend.src_rgb_factor;
+			m_render_state.blending.dst_rgb_factor   = blend.dst_rgb_factor;
+			m_render_state.blending.src_alpha_factor = blend.src_alpha_factor;
+			m_render_state.blending.dst_alpha_factor = blend.dst_alpha_factor; 
+		}
+
+		if ((m_render_state.blending.rgb_equation   != blend.rgb_equation ) ||
+			(m_render_state.blending.alpha_equation != blend.alpha_equation ))
+		{
+			glBlendEquationSeparate(
+				blending_equation_to_enum( blend.rgb_equation ),
+				blending_equation_to_enum( blend.alpha_equation )
+			);
+
+			m_render_state.blending.rgb_equation   = blend.rgb_equation;
+			m_render_state.blending.alpha_equation = blend.alpha_equation;
+		}
+
+		if (( m_render_state.blending.color != blend.color ))
+		{
+			glBlendColor( blend.color.r, blend.color.g, blend.color.b, blend.color.a );
+			m_render_state.blending.color = blend.color;
+		}
+	}
+}
+
+
+void gl_context::apply_culling( const culling& cull )
+{
+	if ( m_render_state.culling.enabled != cull.enabled )
+	{
+		enable( GL_CULL_FACE, cull.enabled );
+		m_render_state.culling.enabled = cull.enabled;
+	}
+
+	if ( cull.enabled )
+	{
+		if ( m_render_state.culling.face != cull.face )
+		{
+			glCullFace( culling_face_type_to_enum(cull.face) );
+			m_render_state.culling.face = cull.face;
+		}
+
+		if ( m_render_state.culling.order != cull.order )
+		{
+			glFrontFace( culling_order_type_to_enum( cull.order ) );
+			m_render_state.culling.order = cull.order;
+		}
+	}
+}
+
+
+void gl_context::force_apply_render_state( const render_state& state )
+{
+	enable( GL_CULL_FACE, state.culling.enabled );
+	glCullFace( culling_face_type_to_enum( state.culling.face ) );
+	glFrontFace( culling_order_type_to_enum( state.culling.order ) );
+
+	enable( GL_SCISSOR_TEST, state.scissor_test.enabled );
+	glScissor( 
+		state.scissor_test.pos.x, state.scissor_test.pos.y, 
+		state.scissor_test.dim.x, state.scissor_test.dim.y 
+	);
+
+	enable( GL_STENCIL_TEST, state.stencil_test.enabled );
+	force_apply_stencil_face( GL_FRONT, state.stencil_test.front_face );
+	force_apply_stencil_face( GL_BACK,  state.stencil_test.back_face  );
+
+	enable( GL_DEPTH_TEST, state.depth_test.enabled );
+	glDepthFunc( depth_state_function_to_enum( state.depth_test.function ) );
+	glDepthRange( state.depth_range.near, state.depth_range.far );
+
+	enable( GL_BLEND, state.blending.enabled );
+	glBlendFuncSeparate(
+		blending_factor_to_enum( state.blending.src_rgb_factor ),
+		blending_factor_to_enum( state.blending.dst_rgb_factor ),
+		blending_factor_to_enum( state.blending.src_alpha_factor ),
+		blending_factor_to_enum( state.blending.dst_alpha_factor )
+	);
+	glBlendEquationSeparate(
+		blending_equation_to_enum( state.blending.rgb_equation ),
+		blending_equation_to_enum( state.blending.alpha_equation )
+	);
+	glBlendColor( 
+		state.blending.color.r, state.blending.color.g, 
+		state.blending.color.b, state.blending.color.a 
+	);
+
+	glDepthMask( state.depth_mask );
+	glColorMask( 
+		state.color_mask.red, state.color_mask.green, 
+		state.color_mask.blue, state.color_mask.alpha 
+	);
+}
+
+void gl_context::force_apply_stencil_face( int face, const stencil_test_face& stencil )
+{
+	glStencilOpSeparate( face,
+		stencil_operation_to_enum( stencil.op_fail ),
+		stencil_operation_to_enum( stencil.op_depth_fail ),
+		stencil_operation_to_enum( stencil.op_depth_pass )
+	);
+
+	glStencilFuncSeparate( face,
+		stencil_function_to_enum( stencil.function ),
+		stencil.ref_value,
+		stencil.mask
+	);
+}
+
+
+void gl_context::apply_render_state( const render_state& state )
+{
+	// apply_primitive_restart
+	apply_culling( state.culling );
+	// apply_program_point_size
+	// apply_rasterization_mode
+	apply_scissor_test( state.scissor_test );
+	apply_stencil_test( state.stencil_test );
+	apply_depth_test( state.depth_test );
+	apply_depth_range( state.depth_range );
+	apply_blending( state.blending );
+	apply_color_mask( state.color_mask );
+	apply_depth_mask( state.depth_mask );
+}
+
Index: trunk/src/gl/gl_program.cc
===================================================================
--- trunk/src/gl/gl_program.cc	(revision 36)
+++ trunk/src/gl/gl_program.cc	(revision 37)
@@ -73,8 +73,8 @@
 }
 
-gl_program::gl_program( const string& vertex_program, const string& fragment_program, const string& geometry_program /*= ""*/ )
-	: vertex_shader( GL_VERTEX_SHADER ), fragment_shader( GL_FRAGMENT_SHADER ), geometry_shader( GL_GEOMETRY_SHADER )
-{
-	compile( vertex_program, fragment_program, geometry_program );
+gl_program::gl_program( const string& vertex_program, const string& fragment_program )
+	: vertex_shader( GL_VERTEX_SHADER ), fragment_shader( GL_FRAGMENT_SHADER )
+{
+	compile( vertex_program, fragment_program );
 }
 
@@ -86,26 +86,14 @@
 		glDetachShader( m_name.get_value(), vertex_shader.get_id() );
 		glDetachShader( m_name.get_value(), fragment_shader.get_id() );
-		if ( geometry_shader.is_valid() )
-		{
-			glDetachShader( m_name.get_value(), geometry_shader.get_id() );
-		}
-	}
-}
-
-bool gl_program::compile( const string& vertex_program, const string& fragment_program, const string& geometry_program /*= "" */ )
+	}
+}
+
+bool gl_program::compile( const string& vertex_program, const string& fragment_program )
 {
 	if (!vertex_shader.compile( vertex_program )) { return false; }
 	if (!fragment_shader.compile( fragment_program )) { return false; }
-	if (!geometry_program.empty())
-	{
-		if (!geometry_shader.compile( geometry_program )) { return false; }
-	}
 
 	glAttachShader( m_name.get_value(), fragment_shader.get_id() );
 	glAttachShader( m_name.get_value(), vertex_shader.get_id() );
-	if (!geometry_program.empty())
-	{
-		glAttachShader( m_name.get_value(), geometry_shader.get_id() );
-	}
 	glLinkProgram( m_name.get_value() );
 
@@ -180,5 +168,5 @@
 		int uni_loc = glGetUniformLocation( m_name.get_value(), name.c_str() );
 		type utype = gl_enum_to_type( uni_type );
-		m_uniform_map[ name ] = create_uniform( gl_enum_to_type( uni_type ), name, uni_loc, uni_len );
+		m_uniform_map[ name ] = create_uniform( utype, name, uni_loc, uni_len );
 	}
 }
