protected void InitGL()
        {
            // intialize GL extensions and check capabilites
            glSupport.InitializeExtensions();

            // log hardware info
            LogManager.Instance.Write("Vendor: {0}", glSupport.Vendor);
            LogManager.Instance.Write("Video Board: {0}", glSupport.VideoCard);
            LogManager.Instance.Write("Version: {0}", glSupport.Version);

            LogManager.Instance.Write("Extensions supported:");

            foreach(string ext in glSupport.Extensions) {
                LogManager.Instance.Write(ext);
            }

            // create our special program manager
            gpuProgramMgr = new GLGpuProgramManager();

            // query hardware capabilites
            CheckCaps();

            // create a specialized instance, which registers itself as the singleton instance of HardwareBufferManager
            // use software buffers as a fallback, which operate as regular vertex arrays
            if(caps.CheckCap(Capabilities.VertexBuffer)) {
                hardwareBufferManager = new GLHardwareBufferManager();
            }
            else {
                hardwareBufferManager = new GLSoftwareBufferManager();
            }

            // by creating our texture manager, singleton TextureManager will hold our implementation
            textureMgr = new GLTextureManager();

            isGLInitialized = true;
        }
		public override void InitializeFromRenderSystemCapabilities( RenderSystemCapabilities caps, RenderTarget primary )
		{
			if ( caps.RendersystemName != Name )
			{
				throw new AxiomException(
					"Trying to initialize GLRenderSystem from RenderSystemCapabilities that do not support OpenGL" );
			}

			// set texture the number of texture units
			this._fixedFunctionTextureUnits = caps.TextureUnitCount;

			//In GL there can be less fixed function texture units than general
			//texture units. Get the minimum of the two.
			if ( caps.HasCapability( Graphics.Capabilities.FragmentPrograms ) )
			{
				int maxTexCoords;
				Gl.glGetIntegerv( Gl.GL_MAX_TEXTURE_COORDS_ARB, out maxTexCoords );
				if ( this._fixedFunctionTextureUnits > maxTexCoords )
				{
					this._fixedFunctionTextureUnits = maxTexCoords;
				}
			}

			/* Axiom: assume that OpenTK/Tao does this already
			 * otherwise we will need to use delegates for these gl calls ..
			 * 
			if (caps.HasCapability(Graphics.Capabilities.GL15NoVbo))
			{
				// Assign ARB functions same to GL 1.5 version since
				// interface identical

				Gl.glBindBufferARB = Gl.glBindBuffer;
				Gl.glBufferDataARB = Gl.glBufferData;
				Gl.glBufferSubDataARB = Gl.glBufferSubData;
				Gl.glDeleteBuffersARB = Gl.glDeleteBuffers;
				Gl.glGenBuffersARB = Gl.glGenBuffers;
				Gl.glGetBufferParameterivARB = Gl.glGetBufferParameteriv;
				Gl.glGetBufferPointervARB = Gl.glGetBufferPointerv;
				Gl.glGetBufferSubDataARB = Gl.glGetBufferSubData;
				Gl.glIsBufferARB = Gl.glIsBuffer;
				Gl.glMapBufferARB = Gl.glMapBuffer;
				Gl.glUnmapBufferARB = Gl.glUnmapBuffer;
			}
			 */

			if ( caps.HasCapability( Graphics.Capabilities.VertexBuffer ) )
			{
				this._hardwareBufferManager = new GLHardwareBufferManager();
			}
			else
			{
				this._hardwareBufferManager = new GLDefaultHardwareBufferManager();
			}

			// XXX Need to check for nv2 support and make a program manager for it
			// XXX Probably nv1 as well for older cards
			// GPU Program Manager setup
			this.gpuProgramMgr = new GLGpuProgramManager();

			if ( caps.HasCapability( Graphics.Capabilities.VertexPrograms ) )
			{
				if ( caps.IsShaderProfileSupported( "arbvp1" ) )
				{
					this.gpuProgramMgr.RegisterProgramFactory( "arbvp1", new ARBGpuProgramFactory() );
				}

				if ( caps.IsShaderProfileSupported( "vp30" ) )
				{
					this.gpuProgramMgr.RegisterProgramFactory( "vp30", new ARBGpuProgramFactory() );
				}

				if ( caps.IsShaderProfileSupported( "vp40" ) )
				{
					this.gpuProgramMgr.RegisterProgramFactory( "vp40", new ARBGpuProgramFactory() );
				}

				if ( caps.IsShaderProfileSupported( "gp4vp" ) )
				{
					this.gpuProgramMgr.RegisterProgramFactory( "gp4vp", new ARBGpuProgramFactory() );
				}

				if ( caps.IsShaderProfileSupported( "gpu_vp" ) )
				{
					this.gpuProgramMgr.RegisterProgramFactory( "gpu_vp", new ARBGpuProgramFactory() );
				}
			}

			if ( caps.HasCapability( Graphics.Capabilities.GeometryPrograms ) )
			{
				//TODO : Should these be createGLArbGpuProgram or createGLGpuNVparseProgram?
				if ( caps.IsShaderProfileSupported( "nvgp4" ) )
				{
					this.gpuProgramMgr.RegisterProgramFactory( "nvgp4", new ARBGpuProgramFactory() );
				}
				if ( caps.IsShaderProfileSupported( "gp4gp" ) )
				{
					this.gpuProgramMgr.RegisterProgramFactory( "gp4gp", new ARBGpuProgramFactory() );
				}
				if ( caps.IsShaderProfileSupported( "gpu_gp" ) )
				{
					this.gpuProgramMgr.RegisterProgramFactory( "gpu_gp", new ARBGpuProgramFactory() );
				}
			}

			if ( caps.HasCapability( Graphics.Capabilities.FragmentPrograms ) )
			{
				if ( caps.IsShaderProfileSupported( "fp20" ) )
				{
					this.gpuProgramMgr.RegisterProgramFactory( "fp20", new Nvidia.NvparseProgramFactory() );
				}

				if ( caps.IsShaderProfileSupported( "ps_1_4" ) )
				{
					this.gpuProgramMgr.RegisterProgramFactory( "ps_1_4", new ATI.ATIFragmentShaderFactory() );
				}

				if ( caps.IsShaderProfileSupported( "ps_1_3" ) )
				{
					this.gpuProgramMgr.RegisterProgramFactory( "ps_1_3", new ATI.ATIFragmentShaderFactory() );
				}

				if ( caps.IsShaderProfileSupported( "ps_1_2" ) )
				{
					this.gpuProgramMgr.RegisterProgramFactory( "ps_1_2", new ATI.ATIFragmentShaderFactory() );
				}

				if ( caps.IsShaderProfileSupported( "ps_1_1" ) )
				{
					this.gpuProgramMgr.RegisterProgramFactory( "ps_1_1", new ATI.ATIFragmentShaderFactory() );
				}

				if ( caps.IsShaderProfileSupported( "arbfp1" ) )
				{
					this.gpuProgramMgr.RegisterProgramFactory( "arbfp1", new ARBGpuProgramFactory() );
				}

				if ( caps.IsShaderProfileSupported( "fp40" ) )
				{
					this.gpuProgramMgr.RegisterProgramFactory( "fp40", new ARBGpuProgramFactory() );
				}

				if ( caps.IsShaderProfileSupported( "fp30" ) )
				{
					this.gpuProgramMgr.RegisterProgramFactory( "fp30", new ARBGpuProgramFactory() );
				}
			}

			if ( caps.IsShaderProfileSupported( "glsl" ) )
			{
				// NFZ - check for GLSL vertex and fragment shader support successful
				this._GLSLProgramFactory = new GLSL.GLSLProgramFactory();
				HighLevelGpuProgramManager.Instance.AddFactory( this._GLSLProgramFactory );
				LogManager.Instance.Write( "GLSL support detected" );
			}

			/* Axiom: assume that OpenTK/Tao does this already
			 * otherwise we will need to use delegates for these gl calls ..
			 * 
			if ( caps.HasCapability( Graphics.Capabilities.HardwareOcculusion ) )
			{
				if ( caps.HasCapability( Graphics.Capabilities.GL15NoHardwareOcclusion ) )
				{
					// Assign ARB functions same to GL 1.5 version since
					// interface identical
					Gl.glBeginQueryARB = Gl.glBeginQuery;
					Gl.glDeleteQueriesARB = Gl.glDeleteQueries;
					Gl.glEndQueryARB = Gl.glEndQuery;
					Gl.glGenQueriesARB = Gl.glGenQueries;
					Gl.glGetQueryObjectivARB = Gl.glGetQueryObjectiv;
					Gl.glGetQueryObjectuivARB = Gl.glGetQueryObjectuiv;
					Gl.glGetQueryivARB = Gl.glGetQueryiv;
					Gl.glIsQueryARB = Gl.glIsQuery;
				}
			}
			 */

			// Do this after extension function pointers are initialised as the extension
			// is used to probe further capabilities.
			ConfigOption cfi;
			var rttMode = 0;
			if ( ConfigOptions.TryGetValue( "RTT Preferred Mode", out cfi ) )
			{
				if ( cfi.Value == "PBuffer" )
				{
					rttMode = 1;
				}
				else if ( cfi.Value == "Copy" )
				{
					rttMode = 2;
				}
			}


			// Check for framebuffer object extension
			if ( caps.HasCapability( Graphics.Capabilities.FrameBufferObjects ) && rttMode < 1 )
			{
				// Before GL version 2.0, we need to get one of the extensions
				//if(caps.HasCapability(Graphics.Capabilities.FrameBufferObjectsARB))
				//    GLEW_GET_FUN(__glewDrawBuffers) = Gl.glDrawBuffersARB;
				//else if(caps.HasCapability(Graphics.Capabilities.FrameBufferObjectsATI))
				//    GLEW_GET_FUN(__glewDrawBuffers) = Gl.glDrawBuffersATI;

				if ( caps.HasCapability( Graphics.Capabilities.HardwareRenderToTexture ) )
				{
					// Create FBO manager
					LogManager.Instance.Write( "GL: Using GL_EXT_framebuffer_object for rendering to textures (best)" );
					this.rttManager = new GLFBORTTManager( this._glSupport, false );
					caps.SetCapability( Graphics.Capabilities.RTTSeperateDepthBuffer );

					//TODO: Check if we're using OpenGL 3.0 and add RSC_RTT_DEPTHBUFFER_RESOLUTION_LESSEQUAL flag
				}
			}
			else
			{
				// Check GLSupport for PBuffer support
				if ( caps.HasCapability( Graphics.Capabilities.PBuffer ) && rttMode < 2 )
				{
					if ( caps.HasCapability( Graphics.Capabilities.HardwareRenderToTexture ) )
					{
						// Use PBuffers
						this.rttManager = new GLPBRTTManager( this._glSupport, primary );
						LogManager.Instance.Write( "GL: Using PBuffers for rendering to textures" );

						//TODO: Depth buffer sharing in pbuffer is left unsupported
					}
				}
				else
				{
					// No pbuffer support either -- fallback to simplest copying from framebuffer
					this.rttManager = new GLCopyingRTTManager( this._glSupport );
					LogManager.Instance.Write( "GL: Using framebuffer copy for rendering to textures (worst)" );
					LogManager.Instance.Write( "GL: Warning: RenderTexture size is restricted to size of framebuffer. If you are on Linux, consider using GLX instead of SDL." );

					//Copy method uses the main depth buffer but no other depth buffer
					caps.SetCapability( Graphics.Capabilities.RTTMainDepthbufferAttachable );
					caps.SetCapability( Graphics.Capabilities.RTTDepthbufferResolutionLessEqual );
				}

				// Downgrade number of simultaneous targets
				caps.MultiRenderTargetCount = 1;
			}

			var defaultLog = LogManager.Instance.DefaultLog;
			if ( defaultLog != null )
			{
				caps.Log( defaultLog );
			}

			// Create the texture manager        
			textureManager = new GLTextureManager( this._glSupport );

			this._glInitialised = true;
		}
        public override void InitializeFromRenderSystemCapabilities(RenderSystemCapabilities caps, RenderTarget primary)
        {
            if (caps.RendersystemName != Name)
            {
                throw new AxiomException(
                          "Trying to initialize GLRenderSystem from RenderSystemCapabilities that do not support OpenGL");
            }

            // set texture the number of texture units
            this._fixedFunctionTextureUnits = caps.TextureUnitCount;

            //In GL there can be less fixed function texture units than general
            //texture units. Get the minimum of the two.
            if (caps.HasCapability(Graphics.Capabilities.FragmentPrograms))
            {
                int maxTexCoords;
                Gl.glGetIntegerv(Gl.GL_MAX_TEXTURE_COORDS_ARB, out maxTexCoords);
                if (this._fixedFunctionTextureUnits > maxTexCoords)
                {
                    this._fixedFunctionTextureUnits = maxTexCoords;
                }
            }

            /* Axiom: assume that OpenTK/Tao does this already
             * otherwise we will need to use delegates for these gl calls ..
             *
             *          if (caps.HasCapability(Graphics.Capabilities.GL15NoVbo))
             *          {
             *                  // Assign ARB functions same to GL 1.5 version since
             *                  // interface identical
             *
             *                  Gl.glBindBufferARB = Gl.glBindBuffer;
             *                  Gl.glBufferDataARB = Gl.glBufferData;
             *                  Gl.glBufferSubDataARB = Gl.glBufferSubData;
             *                  Gl.glDeleteBuffersARB = Gl.glDeleteBuffers;
             *                  Gl.glGenBuffersARB = Gl.glGenBuffers;
             *                  Gl.glGetBufferParameterivARB = Gl.glGetBufferParameteriv;
             *                  Gl.glGetBufferPointervARB = Gl.glGetBufferPointerv;
             *                  Gl.glGetBufferSubDataARB = Gl.glGetBufferSubData;
             *                  Gl.glIsBufferARB = Gl.glIsBuffer;
             *                  Gl.glMapBufferARB = Gl.glMapBuffer;
             *                  Gl.glUnmapBufferARB = Gl.glUnmapBuffer;
             *          }
             */

            if (caps.HasCapability(Graphics.Capabilities.VertexBuffer))
            {
                this._hardwareBufferManager = new GLHardwareBufferManager();
            }
            else
            {
                this._hardwareBufferManager = new GLDefaultHardwareBufferManager();
            }

            // XXX Need to check for nv2 support and make a program manager for it
            // XXX Probably nv1 as well for older cards
            // GPU Program Manager setup
            this.gpuProgramMgr = new GLGpuProgramManager();

            if (caps.HasCapability(Graphics.Capabilities.VertexPrograms))
            {
                if (caps.IsShaderProfileSupported("arbvp1"))
                {
                    this.gpuProgramMgr.RegisterProgramFactory("arbvp1", new ARBGpuProgramFactory());
                }

                if (caps.IsShaderProfileSupported("vp30"))
                {
                    this.gpuProgramMgr.RegisterProgramFactory("vp30", new ARBGpuProgramFactory());
                }

                if (caps.IsShaderProfileSupported("vp40"))
                {
                    this.gpuProgramMgr.RegisterProgramFactory("vp40", new ARBGpuProgramFactory());
                }

                if (caps.IsShaderProfileSupported("gp4vp"))
                {
                    this.gpuProgramMgr.RegisterProgramFactory("gp4vp", new ARBGpuProgramFactory());
                }

                if (caps.IsShaderProfileSupported("gpu_vp"))
                {
                    this.gpuProgramMgr.RegisterProgramFactory("gpu_vp", new ARBGpuProgramFactory());
                }
            }

            if (caps.HasCapability(Graphics.Capabilities.GeometryPrograms))
            {
                //TODO : Should these be createGLArbGpuProgram or createGLGpuNVparseProgram?
                if (caps.IsShaderProfileSupported("nvgp4"))
                {
                    this.gpuProgramMgr.RegisterProgramFactory("nvgp4", new ARBGpuProgramFactory());
                }
                if (caps.IsShaderProfileSupported("gp4gp"))
                {
                    this.gpuProgramMgr.RegisterProgramFactory("gp4gp", new ARBGpuProgramFactory());
                }
                if (caps.IsShaderProfileSupported("gpu_gp"))
                {
                    this.gpuProgramMgr.RegisterProgramFactory("gpu_gp", new ARBGpuProgramFactory());
                }
            }

            if (caps.HasCapability(Graphics.Capabilities.FragmentPrograms))
            {
                if (caps.IsShaderProfileSupported("fp20"))
                {
                    this.gpuProgramMgr.RegisterProgramFactory("fp20", new Nvidia.NvparseProgramFactory());
                }

                if (caps.IsShaderProfileSupported("ps_1_4"))
                {
                    this.gpuProgramMgr.RegisterProgramFactory("ps_1_4", new ATI.ATIFragmentShaderFactory());
                }

                if (caps.IsShaderProfileSupported("ps_1_3"))
                {
                    this.gpuProgramMgr.RegisterProgramFactory("ps_1_3", new ATI.ATIFragmentShaderFactory());
                }

                if (caps.IsShaderProfileSupported("ps_1_2"))
                {
                    this.gpuProgramMgr.RegisterProgramFactory("ps_1_2", new ATI.ATIFragmentShaderFactory());
                }

                if (caps.IsShaderProfileSupported("ps_1_1"))
                {
                    this.gpuProgramMgr.RegisterProgramFactory("ps_1_1", new ATI.ATIFragmentShaderFactory());
                }

                if (caps.IsShaderProfileSupported("arbfp1"))
                {
                    this.gpuProgramMgr.RegisterProgramFactory("arbfp1", new ARBGpuProgramFactory());
                }

                if (caps.IsShaderProfileSupported("fp40"))
                {
                    this.gpuProgramMgr.RegisterProgramFactory("fp40", new ARBGpuProgramFactory());
                }

                if (caps.IsShaderProfileSupported("fp30"))
                {
                    this.gpuProgramMgr.RegisterProgramFactory("fp30", new ARBGpuProgramFactory());
                }
            }

            if (caps.IsShaderProfileSupported("glsl"))
            {
                // NFZ - check for GLSL vertex and fragment shader support successful
                this._GLSLProgramFactory = new GLSL.GLSLProgramFactory();
                HighLevelGpuProgramManager.Instance.AddFactory(this._GLSLProgramFactory);
                LogManager.Instance.Write("GLSL support detected");
            }

            /* Axiom: assume that OpenTK/Tao does this already
             * otherwise we will need to use delegates for these gl calls ..
             *
             *          if ( caps.HasCapability( Graphics.Capabilities.HardwareOcculusion ) )
             *          {
             *                  if ( caps.HasCapability( Graphics.Capabilities.GL15NoHardwareOcclusion ) )
             *                  {
             *                          // Assign ARB functions same to GL 1.5 version since
             *                          // interface identical
             *                          Gl.glBeginQueryARB = Gl.glBeginQuery;
             *                          Gl.glDeleteQueriesARB = Gl.glDeleteQueries;
             *                          Gl.glEndQueryARB = Gl.glEndQuery;
             *                          Gl.glGenQueriesARB = Gl.glGenQueries;
             *                          Gl.glGetQueryObjectivARB = Gl.glGetQueryObjectiv;
             *                          Gl.glGetQueryObjectuivARB = Gl.glGetQueryObjectuiv;
             *                          Gl.glGetQueryivARB = Gl.glGetQueryiv;
             *                          Gl.glIsQueryARB = Gl.glIsQuery;
             *                  }
             *          }
             */

            // Do this after extension function pointers are initialised as the extension
            // is used to probe further capabilities.
            ConfigOption cfi;
            var          rttMode = 0;

            if (ConfigOptions.TryGetValue("RTT Preferred Mode", out cfi))
            {
                if (cfi.Value == "PBuffer")
                {
                    rttMode = 1;
                }
                else if (cfi.Value == "Copy")
                {
                    rttMode = 2;
                }
            }


            // Check for framebuffer object extension
            if (caps.HasCapability(Graphics.Capabilities.FrameBufferObjects) && rttMode < 1)
            {
                // Before GL version 2.0, we need to get one of the extensions
                //if(caps.HasCapability(Graphics.Capabilities.FrameBufferObjectsARB))
                //    GLEW_GET_FUN(__glewDrawBuffers) = Gl.glDrawBuffersARB;
                //else if(caps.HasCapability(Graphics.Capabilities.FrameBufferObjectsATI))
                //    GLEW_GET_FUN(__glewDrawBuffers) = Gl.glDrawBuffersATI;

                if (caps.HasCapability(Graphics.Capabilities.HardwareRenderToTexture))
                {
                    // Create FBO manager
                    LogManager.Instance.Write("GL: Using GL_EXT_framebuffer_object for rendering to textures (best)");
                    this.rttManager = new GLFBORTTManager(this._glSupport, false);
                    caps.SetCapability(Graphics.Capabilities.RTTSeperateDepthBuffer);

                    //TODO: Check if we're using OpenGL 3.0 and add RSC_RTT_DEPTHBUFFER_RESOLUTION_LESSEQUAL flag
                }
            }
            else
            {
                // Check GLSupport for PBuffer support
                if (caps.HasCapability(Graphics.Capabilities.PBuffer) && rttMode < 2)
                {
                    if (caps.HasCapability(Graphics.Capabilities.HardwareRenderToTexture))
                    {
                        // Use PBuffers
                        this.rttManager = new GLPBRTTManager(this._glSupport, primary);
                        LogManager.Instance.Write("GL: Using PBuffers for rendering to textures");

                        //TODO: Depth buffer sharing in pbuffer is left unsupported
                    }
                }
                else
                {
                    // No pbuffer support either -- fallback to simplest copying from framebuffer
                    this.rttManager = new GLCopyingRTTManager(this._glSupport);
                    LogManager.Instance.Write("GL: Using framebuffer copy for rendering to textures (worst)");
                    LogManager.Instance.Write("GL: Warning: RenderTexture size is restricted to size of framebuffer. If you are on Linux, consider using GLX instead of SDL.");

                    //Copy method uses the main depth buffer but no other depth buffer
                    caps.SetCapability(Graphics.Capabilities.RTTMainDepthbufferAttachable);
                    caps.SetCapability(Graphics.Capabilities.RTTDepthbufferResolutionLessEqual);
                }

                // Downgrade number of simultaneous targets
                caps.MultiRenderTargetCount = 1;
            }

            var defaultLog = LogManager.Instance.DefaultLog;

            if (defaultLog != null)
            {
                caps.Log(defaultLog);
            }

            // Create the texture manager
            textureManager = new GLTextureManager(this._glSupport);

            this._glInitialised = true;
        }