private void _convertVertexShaderCaps( RenderSystemCapabilities rsc )
		{
			var major = 0xFF;
			var minor = 0xFF;
			var minVsCaps = new D3D9.Capabilities();

			// Find the device with the lowest vertex shader caps.
			foreach ( var pCurDriver in this._driverList )
			{
				var rkCurCaps = pCurDriver.D3D9DeviceCaps;
				var currMajor = rkCurCaps.VertexShaderVersion.Major;
				var currMinor = rkCurCaps.VertexShaderVersion.Minor;

				if ( currMajor < major )
				{
					major = currMajor;
					minor = currMinor;
					minVsCaps = rkCurCaps;
				}
				else if ( currMajor == major && currMinor < minor )
				{
					minor = currMinor;
					minVsCaps = rkCurCaps;
				}
			}

			var vs2x = false;
			var vs2a = false;

			// Special case detection for vs_2_x/a support
			if ( major >= 2 )
			{
				if ( ( minVsCaps.VS20Caps.Caps & D3D9.VertexShaderCaps.Predication ) != 0 &&
				     ( minVsCaps.VS20Caps.DynamicFlowControlDepth > 0 ) && ( minVsCaps.VS20Caps.TempCount >= 12 ) )
				{
					vs2x = true;
				}

				if ( ( minVsCaps.VS20Caps.Caps & D3D9.VertexShaderCaps.Predication ) != 0 &&
				     ( minVsCaps.VS20Caps.DynamicFlowControlDepth > 0 ) && ( minVsCaps.VS20Caps.TempCount >= 13 ) )
				{
					vs2a = true;
				}
			}

			// Populate max param count
			switch ( major )
			{
				case 1:
					// No boolean params allowed
					rsc.VertexProgramConstantBoolCount = 0;
					// No integer params allowed
					rsc.VertexProgramConstantIntCount = 0;
					// float params, always 4D
					rsc.VertexProgramConstantFloatCount = minVsCaps.MaxVertexShaderConst;
					break;

				case 2:
					// 16 boolean params allowed
					rsc.VertexProgramConstantBoolCount = 16;
					// 16 integer params allowed, 4D
					rsc.VertexProgramConstantIntCount = 16;
					// float params, always 4D
					rsc.VertexProgramConstantFloatCount = minVsCaps.MaxVertexShaderConst;
					break;

				case 3:
					// 16 boolean params allowed
					rsc.VertexProgramConstantBoolCount = 16;
					// 16 integer params allowed, 4D
					rsc.VertexProgramConstantIntCount = 16;
					// float params, always 4D
					rsc.VertexProgramConstantFloatCount = minVsCaps.MaxVertexShaderConst;
					break;
			}

			// populate syntax codes in program manager (no breaks in this one so it falls through)
			switch ( major )
			{
				case 3:
					rsc.AddShaderProfile( "vs_3_0" );
					goto case 2;

				case 2:
					if ( vs2x )
					{
						rsc.AddShaderProfile( "vs_2_x" );
					}
					if ( vs2a )
					{
						rsc.AddShaderProfile( "vs_2_a" );
					}

					rsc.AddShaderProfile( "vs_2_0" );
					goto case 1;

				case 1:
					rsc.AddShaderProfile( "vs_1_1" );
					rsc.SetCapability( Graphics.Capabilities.VertexPrograms );
					break;
			}
		}
        public override RenderSystemCapabilities CreateRenderSystemCapabilities()
        {
            var rsc = new RenderSystemCapabilities();

            rsc.SetCategoryRelevant(CapabilitiesCategory.GL, true);
            rsc.DriverVersion = driverVersion;
            var deviceName = Gl.glGetString(Gl.GL_RENDERER);
            var vendorName = Gl.glGetString(Gl.GL_VENDOR);

            rsc.DeviceName       = deviceName;
            rsc.RendersystemName = Name;

            // determine vendor
            if (vendorName.Contains("NVIDIA"))
            {
                rsc.Vendor = GPUVendor.Nvidia;
            }
            else if (vendorName.Contains("ATI"))
            {
                rsc.Vendor = GPUVendor.Ati;
            }
            else if (vendorName.Contains("Intel"))
            {
                rsc.Vendor = GPUVendor.Intel;
            }
            else if (vendorName.Contains("S3"))
            {
                rsc.Vendor = GPUVendor.S3;
            }
            else if (vendorName.Contains("Matrox"))
            {
                rsc.Vendor = GPUVendor.Matrox;
            }
            else if (vendorName.Contains("3DLabs"))
            {
                rsc.Vendor = GPUVendor._3DLabs;
            }
            else if (vendorName.Contains("SiS"))
            {
                rsc.Vendor = GPUVendor.Sis;
            }
            else
            {
                rsc.Vendor = GPUVendor.Unknown;
            }

            rsc.SetCapability(Graphics.Capabilities.FixedFunction);


            if (this.GLEW_VERSION_1_4 || this.GLEW_SGIS_generate_mipmap)
            {
                var disableAutoMip = false;
#if AXIOM_PLATFORM == AXIOM_PLATFORM_APPLE || AXIOM_PLATFORM == AXIOM_PLATFORM_LINUX
                // Apple & Linux ATI drivers have faults in hardware mipmap generation
                if (rsc.Vendor == GPUVendor.Ati)
                {
                    disableAutoMip = true;
                }
#endif
                // The Intel 915G frequently corrupts textures when using hardware mip generation
                // I'm not currently sure how many generations of hardware this affects,
                // so for now, be safe.
                if (rsc.Vendor == GPUVendor.Intel)
                {
                    disableAutoMip = true;
                }

                // SiS chipsets also seem to have problems with this
                if (rsc.Vendor == GPUVendor.Sis)
                {
                    disableAutoMip = true;
                }

                if (!disableAutoMip)
                {
                    rsc.SetCapability(Graphics.Capabilities.HardwareMipMaps);
                }
            }

            // Check for blending support
            if (this.GLEW_VERSION_1_3 || this.GLEW_ARB_texture_env_combine || this.GLEW_EXT_texture_env_combine)
            {
                rsc.SetCapability(Graphics.Capabilities.Blending);
            }

            // Check for Multitexturing support and set number of texture units
            if (this.GLEW_VERSION_1_3 || this.GLEW_ARB_multitexture)
            {
                int units;
                Gl.glGetIntegerv(Gl.GL_MAX_TEXTURE_UNITS, out units);

                if (this.GLEW_ARB_fragment_program)
                {
                    // Also check GL_MAX_TEXTURE_IMAGE_UNITS_ARB since NV at least
                    // only increased this on the FX/6x00 series
                    int arbUnits;
                    Gl.glGetIntegerv(Gl.GL_MAX_TEXTURE_IMAGE_UNITS_ARB, out arbUnits);
                    if (arbUnits > units)
                    {
                        units = arbUnits;
                    }
                }
                rsc.TextureUnitCount = units;
            }
            else
            {
                // If no multitexture support then set one texture unit
                rsc.TextureUnitCount = 1;
            }

            // Check for Anisotropy support
            if (this.GLEW_EXT_texture_filter_anisotropic)
            {
                rsc.SetCapability(Graphics.Capabilities.AnisotropicFiltering);
            }

            // Check for DOT3 support
            if (this.GLEW_VERSION_1_3 || this.GLEW_ARB_texture_env_dot3 || this.GLEW_EXT_texture_env_dot3)
            {
                rsc.SetCapability(Graphics.Capabilities.Dot3);
            }

            // Check for cube mapping
            if (this.GLEW_VERSION_1_3 || this.GLEW_ARB_texture_cube_map || this.GLEW_EXT_texture_cube_map)
            {
                rsc.SetCapability(Graphics.Capabilities.CubeMapping);
            }

            // Point sprites
            if (this.GLEW_VERSION_2_0 || this.GLEW_ARB_point_sprite)
            {
                rsc.SetCapability(Graphics.Capabilities.PointSprites);
            }
            // Check for point parameters
            if (this.GLEW_VERSION_1_4)
            {
                rsc.SetCapability(Graphics.Capabilities.PointExtendedParameters);
            }
            if (this.GLEW_ARB_point_parameters)
            {
                rsc.SetCapability(Graphics.Capabilities.PointExtendedParametersARB);
            }
            if (this.GLEW_EXT_point_parameters)
            {
                rsc.SetCapability(Graphics.Capabilities.PointExtendedParametersEXT);
            }

            // Check for hardware stencil support and set bit depth
            int stencil;
            Gl.glGetIntegerv(Gl.GL_STENCIL_BITS, out stencil);

            if (stencil != 0)
            {
                rsc.SetCapability(Graphics.Capabilities.StencilBuffer);
                rsc.StencilBufferBitCount = stencil;
            }

            if (this.GLEW_VERSION_1_5 || this.GLEW_ARB_vertex_buffer_object)
            {
                if (!this.GLEW_ARB_vertex_buffer_object)
                {
                    rsc.SetCapability(Graphics.Capabilities.GL15NoVbo);
                }
                rsc.SetCapability(Graphics.Capabilities.VertexBuffer);
            }

            if (this.GLEW_ARB_vertex_program)
            {
                rsc.SetCapability(Graphics.Capabilities.VertexPrograms);

                // Vertex Program Properties
                rsc.VertexProgramConstantBoolCount = 0;
                rsc.VertexProgramConstantIntCount  = 0;

                int floatConstantCount;
                Gl.glGetProgramivARB(Gl.GL_VERTEX_PROGRAM_ARB, Gl.GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB, out floatConstantCount);
                rsc.VertexProgramConstantFloatCount = floatConstantCount;

                rsc.AddShaderProfile("arbvp1");
                if (this.GLEW_NV_vertex_program2_option)
                {
                    rsc.AddShaderProfile("vp30");
                }

                if (this.GLEW_NV_vertex_program3)
                {
                    rsc.AddShaderProfile("vp40");
                }

                if (this.GLEW_NV_vertex_program4)
                {
                    rsc.AddShaderProfile("gp4vp");
                    rsc.AddShaderProfile("gpu_vp");
                }
            }

            if (this.GLEW_NV_register_combiners2 && this.GLEW_NV_texture_shader)
            {
                rsc.SetCapability(Graphics.Capabilities.FragmentPrograms);
                rsc.AddShaderProfile("fp20");
            }

            // NFZ - check for ATI fragment shader support
            if (this.GLEW_ATI_fragment_shader)
            {
                rsc.SetCapability(Graphics.Capabilities.FragmentPrograms);
                // no boolean params allowed
                rsc.FragmentProgramConstantBoolCount = 0;
                // no integer params allowed
                rsc.FragmentProgramConstantIntCount = 0;

                // only 8 Vector4 constant floats supported
                rsc.FragmentProgramConstantFloatCount = 8;

                rsc.AddShaderProfile("ps_1_4");
                rsc.AddShaderProfile("ps_1_3");
                rsc.AddShaderProfile("ps_1_2");
                rsc.AddShaderProfile("ps_1_1");
            }

            if (this.GLEW_ARB_fragment_program)
            {
                rsc.SetCapability(Graphics.Capabilities.FragmentPrograms);

                // Fragment Program Properties
                rsc.FragmentProgramConstantBoolCount = 0;
                rsc.FragmentProgramConstantIntCount  = 0;

                int floatConstantCount;
                Gl.glGetProgramivARB(Gl.GL_FRAGMENT_PROGRAM_ARB, Gl.GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB, out floatConstantCount);
                rsc.FragmentProgramConstantFloatCount = floatConstantCount;

                rsc.AddShaderProfile("arbfp1");
                if (this.GLEW_NV_fragment_program_option)
                {
                    rsc.AddShaderProfile("fp30");
                }

                if (this.GLEW_NV_fragment_program2)
                {
                    rsc.AddShaderProfile("fp40");
                }
            }

            // NFZ - Check if GLSL is supported
            if (this.GLEW_VERSION_2_0 ||
                (this.GLEW_ARB_shading_language_100 && this.GLEW_ARB_shader_objects && this.GLEW_ARB_fragment_shader &&
                 this.GLEW_ARB_vertex_shader))
            {
                rsc.AddShaderProfile("glsl");
            }

            // Check if geometry shaders are supported
            if (this.GLEW_VERSION_2_0 && this.GLEW_EXT_geometry_shader4)
            {
                rsc.SetCapability(Graphics.Capabilities.GeometryPrograms);
                rsc.AddShaderProfile("nvgp4");

                //Also add the CG profiles
                rsc.AddShaderProfile("gpu_gp");
                rsc.AddShaderProfile("gp4gp");

                rsc.GeometryProgramConstantBoolCount = 0;
                rsc.GeometryProgramConstantIntCount  = 0;

                int floatConstantCount;
                Gl.glGetProgramivARB(Gl.GL_GEOMETRY_PROGRAM_NV, Gl.GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB, out floatConstantCount);
                rsc.GeometryProgramConstantFloatCount = floatConstantCount;

                int maxOutputVertices;
                Gl.glGetIntegerv(Gl.GL_MAX_GEOMETRY_OUTPUT_VERTICES_EXT, out maxOutputVertices);
                rsc.GeometryProgramNumOutputVertices = maxOutputVertices;
            }

            if (this._glSupport.CheckExtension("GL_ARB_get_program_binary"))
            {
                // states 3.0 here: http://developer.download.nvidia.com/opengl/specs/GL_ARB_get_program_binary.txt
                // but not here: http://www.opengl.org/sdk/docs/man4/xhtml/glGetProgramBinary.xml
                // and here states 4.1: http://www.geeks3d.com/20100727/opengl-4-1-allows-the-use-of-binary-shaders/
                rsc.SetCapability(Graphics.Capabilities.CanGetCompiledShaderBuffer);
            }

            if (this.GLEW_VERSION_3_3)
            {
                // states 3.3 here: http://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttribDivisor.xml
                rsc.SetCapability(Graphics.Capabilities.VertexBufferInstanceData);
            }

            //Check if render to vertex buffer (transform feedback in OpenGL)
            if (this.GLEW_VERSION_2_0 && this.GLEW_NV_transform_feedback)
            {
                rsc.SetCapability(Graphics.Capabilities.HardwareRenderToTexture);
            }

            // Check for texture compression
            if (this.GLEW_VERSION_1_3 || this.GLEW_ARB_texture_compression)
            {
                rsc.SetCapability(Graphics.Capabilities.TextureCompression);

                // Check for dxt compression
                if (this.GLEW_EXT_texture_compression_s3tc)
                {
#if __APPLE__ && __PPC__
                    // Apple on ATI & PPC has errors in DXT
                    if (_glSupport.Vendor.Contains("ATI") == false)
#endif
                    rsc.SetCapability(Graphics.Capabilities.TextureCompressionDXT);
                }
                // Check for vtc compression
                if (this.GLEW_NV_texture_compression_vtc)
                {
                    rsc.SetCapability(Graphics.Capabilities.TextureCompressionVTC);
                }
            }

            // Scissor test is standard in GL 1.2 (is it emulated on some cards though?)
            rsc.SetCapability(Graphics.Capabilities.ScissorTest);
            // As are user clipping planes
            rsc.SetCapability(Graphics.Capabilities.UserClipPlanes);

            // 2-sided stencil?
            if (this.GLEW_VERSION_2_0 || this.GLEW_EXT_stencil_two_side)
            {
                rsc.SetCapability(Graphics.Capabilities.TwoSidedStencil);
            }
            // stencil wrapping?
            if (this.GLEW_VERSION_1_4 || this.GLEW_EXT_stencil_wrap)
            {
                rsc.SetCapability(Graphics.Capabilities.StencilWrap);
            }

            // Check for hardware occlusion support
            if (this.GLEW_VERSION_1_5 || this.GLEW_ARB_occlusion_query)
            {
                // Some buggy driver claim that it is GL 1.5 compliant and
                // not support ARB_occlusion_query
                if (!this.GLEW_ARB_occlusion_query)
                {
                    rsc.SetCapability(Graphics.Capabilities.GL15NoHardwareOcclusion);
                }

                rsc.SetCapability(Graphics.Capabilities.HardwareOcculusion);
            }
            else if (this.GLEW_NV_occlusion_query)
            {
                // Support NV extension too for old hardware
                rsc.SetCapability(Graphics.Capabilities.HardwareOcculusion);
            }

            // UBYTE4 always supported
            rsc.SetCapability(Graphics.Capabilities.VertexFormatUByte4);

            // Infinite far plane always supported
            rsc.SetCapability(Graphics.Capabilities.InfiniteFarPlane);

            // Check for non-power-of-2 texture support
            if (this.GLEW_ARB_texture_non_power_of_two)
            {
                rsc.SetCapability(Graphics.Capabilities.NonPowerOf2Textures);
            }

            // Check for Float textures
            if (this.GLEW_ATI_texture_float || this.GLEW_ARB_texture_float)
            {
                rsc.SetCapability(Graphics.Capabilities.TextureFloat);
            }

            // 3D textures should be supported by GL 1.2, which is our minimum version
            rsc.SetCapability(Graphics.Capabilities.Texture3D);

            // Check for framebuffer object extension
            if (this.GLEW_EXT_framebuffer_object)
            {
                // Probe number of draw buffers
                // Only makes sense with FBO support, so probe here
                if (this.GLEW_VERSION_2_0 || this.GLEW_ARB_draw_buffers || this.GLEW_ATI_draw_buffers)
                {
                    int buffers;
                    Gl.glGetIntegerv(Gl.GL_MAX_DRAW_BUFFERS_ARB, out buffers);
                    rsc.MultiRenderTargetCount = Utility.Min(buffers, Config.MaxMultipleRenderTargets);
                    rsc.SetCapability(Graphics.Capabilities.MRTDifferentBitDepths);
                    if (!this.GLEW_VERSION_2_0)
                    {
                        // Before GL version 2.0, we need to get one of the extensions
                        if (this.GLEW_ARB_draw_buffers)
                        {
                            rsc.SetCapability(Graphics.Capabilities.FrameBufferObjectsARB);
                        }
                        if (this.GLEW_ATI_draw_buffers)
                        {
                            rsc.SetCapability(Graphics.Capabilities.FrameBufferObjectsATI);
                        }
                    }
                    // Set FBO flag for all 3 'subtypes'
                    rsc.SetCapability(Graphics.Capabilities.FrameBufferObjects);
                }
                rsc.SetCapability(Graphics.Capabilities.HardwareRenderToTexture);
            }

            // Check GLSupport for PBuffer support
            if (this._glSupport.SupportsPBuffers)
            {
                // Use PBuffers
                rsc.SetCapability(Graphics.Capabilities.HardwareRenderToTexture);
                rsc.SetCapability(Graphics.Capabilities.PBuffer);
            }

            // Point size
            if (this.GLEW_VERSION_1_4)
            {
                float ps;
                Gl.glGetFloatv(Gl.GL_POINT_SIZE_MAX, out ps);
                rsc.MaxPointSize = ps;
            }
            else
            {
                var vSize = new int[2];
                Gl.glGetIntegerv(Gl.GL_POINT_SIZE_RANGE, vSize);
                rsc.MaxPointSize = vSize[1];
            }

            // Vertex texture fetching
            if (this._glSupport.CheckExtension("GL_ARB_vertex_shader"))
            {
                int vUnits;
                Gl.glGetIntegerv(Gl.GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB, out vUnits);
                rsc.VertexTextureUnitCount = vUnits;
                if (vUnits > 0)
                {
                    rsc.SetCapability(Graphics.Capabilities.VertexTextureFetch);
                }
                // GL always shares vertex and fragment texture units (for now?)
                rsc.VertexTextureUnitsShared = true;
            }

            // Mipmap LOD biasing?
            if (this.GLEW_VERSION_1_4 || this.GLEW_EXT_texture_lod_bias)
            {
                rsc.SetCapability(Graphics.Capabilities.MipmapLODBias);
            }

            // Alpha to coverage?
            if (this._glSupport.CheckExtension("GL_ARB_multisample"))
            {
                // Alpha to coverage always 'supported' when MSAA is available
                // although card may ignore it if it doesn't specifically support A2C
                rsc.SetCapability(Graphics.Capabilities.AlphaToCoverage);
            }

            // Advanced blending operations
            if (this.GLEW_VERSION_2_0)
            {
                rsc.SetCapability(Graphics.Capabilities.AdvancedBlendOperations);
            }

            return(rsc);
        }
		public override RenderSystemCapabilities CreateRenderSystemCapabilities()
		{
			var rsc = new RenderSystemCapabilities();

			rsc.SetCategoryRelevant( CapabilitiesCategory.GL, true );
			rsc.DriverVersion = driverVersion;
			var deviceName = Gl.glGetString( Gl.GL_RENDERER );
			var vendorName = Gl.glGetString( Gl.GL_VENDOR );
			rsc.DeviceName = deviceName;
			rsc.RendersystemName = Name;

			// determine vendor
			if ( vendorName.Contains( "NVIDIA" ) )
			{
				rsc.Vendor = GPUVendor.Nvidia;
			}
			else if ( vendorName.Contains( "ATI" ) )
			{
				rsc.Vendor = GPUVendor.Ati;
			}
			else if ( vendorName.Contains( "Intel" ) )
			{
				rsc.Vendor = GPUVendor.Intel;
			}
			else if ( vendorName.Contains( "S3" ) )
			{
				rsc.Vendor = GPUVendor.S3;
			}
			else if ( vendorName.Contains( "Matrox" ) )
			{
				rsc.Vendor = GPUVendor.Matrox;
			}
			else if ( vendorName.Contains( "3DLabs" ) )
			{
				rsc.Vendor = GPUVendor._3DLabs;
			}
			else if ( vendorName.Contains( "SiS" ) )
			{
				rsc.Vendor = GPUVendor.Sis;
			}
			else
			{
				rsc.Vendor = GPUVendor.Unknown;
			}

			rsc.SetCapability( Graphics.Capabilities.FixedFunction );


			if ( this.GLEW_VERSION_1_4 || this.GLEW_SGIS_generate_mipmap )
			{
				var disableAutoMip = false;
#if AXIOM_PLATFORM == AXIOM_PLATFORM_APPLE || AXIOM_PLATFORM == AXIOM_PLATFORM_LINUX
				// Apple & Linux ATI drivers have faults in hardware mipmap generation
				if ( rsc.Vendor == GPUVendor.Ati )
				{
					disableAutoMip = true;
				}
#endif
				// The Intel 915G frequently corrupts textures when using hardware mip generation
				// I'm not currently sure how many generations of hardware this affects, 
				// so for now, be safe.
				if ( rsc.Vendor == GPUVendor.Intel )
				{
					disableAutoMip = true;
				}

				// SiS chipsets also seem to have problems with this
				if ( rsc.Vendor == GPUVendor.Sis )
				{
					disableAutoMip = true;
				}

				if ( !disableAutoMip )
				{
					rsc.SetCapability( Graphics.Capabilities.HardwareMipMaps );
				}
			}

			// Check for blending support
			if ( this.GLEW_VERSION_1_3 || this.GLEW_ARB_texture_env_combine || this.GLEW_EXT_texture_env_combine )
			{
				rsc.SetCapability( Graphics.Capabilities.Blending );
			}

			// Check for Multitexturing support and set number of texture units
			if ( this.GLEW_VERSION_1_3 || this.GLEW_ARB_multitexture )
			{
				int units;
				Gl.glGetIntegerv( Gl.GL_MAX_TEXTURE_UNITS, out units );

				if ( this.GLEW_ARB_fragment_program )
				{
					// Also check GL_MAX_TEXTURE_IMAGE_UNITS_ARB since NV at least
					// only increased this on the FX/6x00 series
					int arbUnits;
					Gl.glGetIntegerv( Gl.GL_MAX_TEXTURE_IMAGE_UNITS_ARB, out arbUnits );
					if ( arbUnits > units )
					{
						units = arbUnits;
					}
				}
				rsc.TextureUnitCount = units;
			}
			else
			{
				// If no multitexture support then set one texture unit
				rsc.TextureUnitCount = 1;
			}

			// Check for Anisotropy support
			if ( this.GLEW_EXT_texture_filter_anisotropic )
			{
				rsc.SetCapability( Graphics.Capabilities.AnisotropicFiltering );
			}

			// Check for DOT3 support
			if ( this.GLEW_VERSION_1_3 || this.GLEW_ARB_texture_env_dot3 || this.GLEW_EXT_texture_env_dot3 )
			{
				rsc.SetCapability( Graphics.Capabilities.Dot3 );
			}

			// Check for cube mapping
			if ( this.GLEW_VERSION_1_3 || this.GLEW_ARB_texture_cube_map || this.GLEW_EXT_texture_cube_map )
			{
				rsc.SetCapability( Graphics.Capabilities.CubeMapping );
			}

			// Point sprites
			if ( this.GLEW_VERSION_2_0 || this.GLEW_ARB_point_sprite )
			{
				rsc.SetCapability( Graphics.Capabilities.PointSprites );
			}
			// Check for point parameters
			if ( this.GLEW_VERSION_1_4 )
			{
				rsc.SetCapability( Graphics.Capabilities.PointExtendedParameters );
			}
			if ( this.GLEW_ARB_point_parameters )
			{
				rsc.SetCapability( Graphics.Capabilities.PointExtendedParametersARB );
			}
			if ( this.GLEW_EXT_point_parameters )
			{
				rsc.SetCapability( Graphics.Capabilities.PointExtendedParametersEXT );
			}

			// Check for hardware stencil support and set bit depth
			int stencil;
			Gl.glGetIntegerv( Gl.GL_STENCIL_BITS, out stencil );

			if ( stencil != 0 )
			{
				rsc.SetCapability( Graphics.Capabilities.StencilBuffer );
				rsc.StencilBufferBitCount = stencil;
			}

			if ( this.GLEW_VERSION_1_5 || this.GLEW_ARB_vertex_buffer_object )
			{
				if ( !this.GLEW_ARB_vertex_buffer_object )
				{
					rsc.SetCapability( Graphics.Capabilities.GL15NoVbo );
				}
				rsc.SetCapability( Graphics.Capabilities.VertexBuffer );
			}

			if ( this.GLEW_ARB_vertex_program )
			{
				rsc.SetCapability( Graphics.Capabilities.VertexPrograms );

				// Vertex Program Properties
				rsc.VertexProgramConstantBoolCount = 0;
				rsc.VertexProgramConstantIntCount = 0;

				int floatConstantCount;
				Gl.glGetProgramivARB( Gl.GL_VERTEX_PROGRAM_ARB, Gl.GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB, out floatConstantCount );
				rsc.VertexProgramConstantFloatCount = floatConstantCount;

				rsc.AddShaderProfile( "arbvp1" );
				if ( this.GLEW_NV_vertex_program2_option )
				{
					rsc.AddShaderProfile( "vp30" );
				}

				if ( this.GLEW_NV_vertex_program3 )
				{
					rsc.AddShaderProfile( "vp40" );
				}

				if ( this.GLEW_NV_vertex_program4 )
				{
					rsc.AddShaderProfile( "gp4vp" );
					rsc.AddShaderProfile( "gpu_vp" );
				}
			}

			if ( this.GLEW_NV_register_combiners2 && this.GLEW_NV_texture_shader )
			{
				rsc.SetCapability( Graphics.Capabilities.FragmentPrograms );
				rsc.AddShaderProfile( "fp20" );
			}

			// NFZ - check for ATI fragment shader support
			if ( this.GLEW_ATI_fragment_shader )
			{
				rsc.SetCapability( Graphics.Capabilities.FragmentPrograms );
				// no boolean params allowed
				rsc.FragmentProgramConstantBoolCount = 0;
				// no integer params allowed
				rsc.FragmentProgramConstantIntCount = 0;

				// only 8 Vector4 constant floats supported
				rsc.FragmentProgramConstantFloatCount = 8;

				rsc.AddShaderProfile( "ps_1_4" );
				rsc.AddShaderProfile( "ps_1_3" );
				rsc.AddShaderProfile( "ps_1_2" );
				rsc.AddShaderProfile( "ps_1_1" );
			}

			if ( this.GLEW_ARB_fragment_program )
			{
				rsc.SetCapability( Graphics.Capabilities.FragmentPrograms );

				// Fragment Program Properties
				rsc.FragmentProgramConstantBoolCount = 0;
				rsc.FragmentProgramConstantIntCount = 0;

				int floatConstantCount;
				Gl.glGetProgramivARB( Gl.GL_FRAGMENT_PROGRAM_ARB, Gl.GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB, out floatConstantCount );
				rsc.FragmentProgramConstantFloatCount = floatConstantCount;

				rsc.AddShaderProfile( "arbfp1" );
				if ( this.GLEW_NV_fragment_program_option )
				{
					rsc.AddShaderProfile( "fp30" );
				}

				if ( this.GLEW_NV_fragment_program2 )
				{
					rsc.AddShaderProfile( "fp40" );
				}
			}

			// NFZ - Check if GLSL is supported
			if ( this.GLEW_VERSION_2_0 ||
				 ( this.GLEW_ARB_shading_language_100 && this.GLEW_ARB_shader_objects && this.GLEW_ARB_fragment_shader &&
				   this.GLEW_ARB_vertex_shader ) )
			{
				rsc.AddShaderProfile( "glsl" );
			}

			// Check if geometry shaders are supported
			if ( this.GLEW_VERSION_2_0 && this.GLEW_EXT_geometry_shader4 )
			{
				rsc.SetCapability( Graphics.Capabilities.GeometryPrograms );
				rsc.AddShaderProfile( "nvgp4" );

				//Also add the CG profiles
				rsc.AddShaderProfile( "gpu_gp" );
				rsc.AddShaderProfile( "gp4gp" );

				rsc.GeometryProgramConstantBoolCount = 0;
				rsc.GeometryProgramConstantIntCount = 0;

				int floatConstantCount;
				Gl.glGetProgramivARB( Gl.GL_GEOMETRY_PROGRAM_NV, Gl.GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB, out floatConstantCount );
				rsc.GeometryProgramConstantFloatCount = floatConstantCount;

				int maxOutputVertices;
				Gl.glGetIntegerv( Gl.GL_MAX_GEOMETRY_OUTPUT_VERTICES_EXT, out maxOutputVertices );
				rsc.GeometryProgramNumOutputVertices = maxOutputVertices;
			}

			if ( this._glSupport.CheckExtension( "GL_ARB_get_program_binary" ) )
			{
				// states 3.0 here: http://developer.download.nvidia.com/opengl/specs/GL_ARB_get_program_binary.txt
				// but not here: http://www.opengl.org/sdk/docs/man4/xhtml/glGetProgramBinary.xml
				// and here states 4.1: http://www.geeks3d.com/20100727/opengl-4-1-allows-the-use-of-binary-shaders/
				rsc.SetCapability( Graphics.Capabilities.CanGetCompiledShaderBuffer );
			}

			if ( this.GLEW_VERSION_3_3 )
			{
				// states 3.3 here: http://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttribDivisor.xml
				rsc.SetCapability( Graphics.Capabilities.VertexBufferInstanceData );
			}

			//Check if render to vertex buffer (transform feedback in OpenGL)
			if ( this.GLEW_VERSION_2_0 && this.GLEW_NV_transform_feedback )
			{
				rsc.SetCapability( Graphics.Capabilities.HardwareRenderToTexture );
			}

			// Check for texture compression
			if ( this.GLEW_VERSION_1_3 || this.GLEW_ARB_texture_compression )
			{
				rsc.SetCapability( Graphics.Capabilities.TextureCompression );

				// Check for dxt compression
				if ( this.GLEW_EXT_texture_compression_s3tc )
				{
#if __APPLE__ && __PPC__
	// Apple on ATI & PPC has errors in DXT
				if (_glSupport.Vendor.Contains("ATI") == false)
	#endif
					rsc.SetCapability( Graphics.Capabilities.TextureCompressionDXT );
				}
				// Check for vtc compression
				if ( this.GLEW_NV_texture_compression_vtc )
				{
					rsc.SetCapability( Graphics.Capabilities.TextureCompressionVTC );
				}
			}

			// Scissor test is standard in GL 1.2 (is it emulated on some cards though?)
			rsc.SetCapability( Graphics.Capabilities.ScissorTest );
			// As are user clipping planes
			rsc.SetCapability( Graphics.Capabilities.UserClipPlanes );

			// 2-sided stencil?
			if ( this.GLEW_VERSION_2_0 || this.GLEW_EXT_stencil_two_side )
			{
				rsc.SetCapability( Graphics.Capabilities.TwoSidedStencil );
			}
			// stencil wrapping?
			if ( this.GLEW_VERSION_1_4 || this.GLEW_EXT_stencil_wrap )
			{
				rsc.SetCapability( Graphics.Capabilities.StencilWrap );
			}

			// Check for hardware occlusion support
			if ( this.GLEW_VERSION_1_5 || this.GLEW_ARB_occlusion_query )
			{
				// Some buggy driver claim that it is GL 1.5 compliant and
				// not support ARB_occlusion_query
				if ( !this.GLEW_ARB_occlusion_query )
				{
					rsc.SetCapability( Graphics.Capabilities.GL15NoHardwareOcclusion );
				}

				rsc.SetCapability( Graphics.Capabilities.HardwareOcculusion );
			}
			else if ( this.GLEW_NV_occlusion_query )
			{
				// Support NV extension too for old hardware
				rsc.SetCapability( Graphics.Capabilities.HardwareOcculusion );
			}

			// UBYTE4 always supported
			rsc.SetCapability( Graphics.Capabilities.VertexFormatUByte4 );

			// Infinite far plane always supported
			rsc.SetCapability( Graphics.Capabilities.InfiniteFarPlane );

			// Check for non-power-of-2 texture support
			if ( this.GLEW_ARB_texture_non_power_of_two )
			{
				rsc.SetCapability( Graphics.Capabilities.NonPowerOf2Textures );
			}

			// Check for Float textures
			if ( this.GLEW_ATI_texture_float || this.GLEW_ARB_texture_float )
			{
				rsc.SetCapability( Graphics.Capabilities.TextureFloat );
			}

			// 3D textures should be supported by GL 1.2, which is our minimum version
			rsc.SetCapability( Graphics.Capabilities.Texture3D );

			// Check for framebuffer object extension
			if ( this.GLEW_EXT_framebuffer_object )
			{
				// Probe number of draw buffers
				// Only makes sense with FBO support, so probe here
				if ( this.GLEW_VERSION_2_0 || this.GLEW_ARB_draw_buffers || this.GLEW_ATI_draw_buffers )
				{
					int buffers;
					Gl.glGetIntegerv( Gl.GL_MAX_DRAW_BUFFERS_ARB, out buffers );
					rsc.MultiRenderTargetCount = Utility.Min( buffers, Config.MaxMultipleRenderTargets );
					rsc.SetCapability( Graphics.Capabilities.MRTDifferentBitDepths );
					if ( !this.GLEW_VERSION_2_0 )
					{
						// Before GL version 2.0, we need to get one of the extensions
						if ( this.GLEW_ARB_draw_buffers )
						{
							rsc.SetCapability( Graphics.Capabilities.FrameBufferObjectsARB );
						}
						if ( this.GLEW_ATI_draw_buffers )
						{
							rsc.SetCapability( Graphics.Capabilities.FrameBufferObjectsATI );
						}
					}
					// Set FBO flag for all 3 'subtypes'
					rsc.SetCapability( Graphics.Capabilities.FrameBufferObjects );
				}
				rsc.SetCapability( Graphics.Capabilities.HardwareRenderToTexture );
			}

			// Check GLSupport for PBuffer support
			if ( this._glSupport.SupportsPBuffers )
			{
				// Use PBuffers
				rsc.SetCapability( Graphics.Capabilities.HardwareRenderToTexture );
				rsc.SetCapability( Graphics.Capabilities.PBuffer );
			}

			// Point size
			if ( this.GLEW_VERSION_1_4 )
			{
				float ps;
				Gl.glGetFloatv( Gl.GL_POINT_SIZE_MAX, out ps );
				rsc.MaxPointSize = ps;
			}
			else
			{
				var vSize = new int[2];
				Gl.glGetIntegerv( Gl.GL_POINT_SIZE_RANGE, vSize );
				rsc.MaxPointSize = vSize[ 1 ];
			}

			// Vertex texture fetching
			if ( this._glSupport.CheckExtension( "GL_ARB_vertex_shader" ) )
			{
				int vUnits;
				Gl.glGetIntegerv( Gl.GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB, out vUnits );
				rsc.VertexTextureUnitCount = vUnits;
				if ( vUnits > 0 )
				{
					rsc.SetCapability( Graphics.Capabilities.VertexTextureFetch );
				}
				// GL always shares vertex and fragment texture units (for now?)
				rsc.VertexTextureUnitsShared = true;
			}

			// Mipmap LOD biasing?
			if ( this.GLEW_VERSION_1_4 || this.GLEW_EXT_texture_lod_bias )
			{
				rsc.SetCapability( Graphics.Capabilities.MipmapLODBias );
			}

			// Alpha to coverage?
			if ( this._glSupport.CheckExtension( "GL_ARB_multisample" ) )
			{
				// Alpha to coverage always 'supported' when MSAA is available
				// although card may ignore it if it doesn't specifically support A2C
				rsc.SetCapability( Graphics.Capabilities.AlphaToCoverage );
			}

			// Advanced blending operations
			if ( this.GLEW_VERSION_2_0 )
			{
				rsc.SetCapability( Graphics.Capabilities.AdvancedBlendOperations );
			}

			return rsc;
		}
		private void _convertPixelShaderCaps( RenderSystemCapabilities rsc )
		{
			var major = 0xFF;
			var minor = 0xFF;
			var minPsCaps = new D3D9.Capabilities();

			// Find the device with the lowest vertex shader caps.
			foreach ( var pCurDriver in this._driverList )
			{
				var currCaps = pCurDriver.D3D9DeviceCaps;
				var currMajor = currCaps.PixelShaderVersion.Major;
				var currMinor = currCaps.PixelShaderVersion.Minor;

				if ( currMajor < major )
				{
					major = currMajor;
					minor = currMinor;
					minPsCaps = currCaps;
				}
				else if ( currMajor == major && currMinor < minor )
				{
					minor = currMinor;
					minPsCaps = currCaps;
				}
			}

			var ps2a = false;
			var ps2b = false;
			var ps2x = false;

			// Special case detection for ps_2_x/a/b support
			if ( major >= 2 )
			{
				if ( ( minPsCaps.PS20Caps.Caps & D3D9.PixelShaderCaps.NoTextureInstructionLimit ) != 0 &&
				     ( minPsCaps.PS20Caps.TempCount >= 32 ) )
				{
					ps2b = true;
				}

				if ( ( minPsCaps.PS20Caps.Caps & D3D9.PixelShaderCaps.NoTextureInstructionLimit ) != 0 &&
				     ( minPsCaps.PS20Caps.Caps & D3D9.PixelShaderCaps.NoDependentReadLimit ) != 0 &&
				     ( minPsCaps.PS20Caps.Caps & D3D9.PixelShaderCaps.ArbitrarySwizzle ) != 0 &&
				     ( minPsCaps.PS20Caps.Caps & D3D9.PixelShaderCaps.GradientInstructions ) != 0 &&
				     ( minPsCaps.PS20Caps.Caps & D3D9.PixelShaderCaps.Predication ) != 0 && ( minPsCaps.PS20Caps.TempCount >= 22 ) )
				{
					ps2a = true;
				}

				// Does this enough?
				if ( ps2a || ps2b )
				{
					ps2x = true;
				}
			}

			switch ( major )
			{
				case 1:
					// no boolean params allowed
					rsc.FragmentProgramConstantBoolCount = 0;
					// no integer params allowed
					rsc.FragmentProgramConstantIntCount = 0;
					// float params, always 4D
					// NB in ps_1_x these are actually stored as fixed point values,
					// but they are entered as floats
					rsc.FragmentProgramConstantFloatCount = 8;
					break;

				case 2:
					// 16 boolean params allowed
					rsc.FragmentProgramConstantBoolCount = 16;
					// 16 integer params allowed, 4D
					rsc.FragmentProgramConstantIntCount = 16;
					// float params, always 4D
					rsc.FragmentProgramConstantFloatCount = 32;
					break;

				case 3:
					// 16 boolean params allowed
					rsc.FragmentProgramConstantBoolCount = 16;
					// 16 integer params allowed, 4D
					rsc.FragmentProgramConstantIntCount = 16;
					// float params, always 4D
					rsc.FragmentProgramConstantFloatCount = 224;
					break;
			}

			// populate syntax codes in program manager (no breaks in this one so it falls through)
			switch ( major )
			{
				case 3:
					if ( minor > 0 )
					{
						rsc.AddShaderProfile( "ps_3_x" );
					}

					rsc.AddShaderProfile( "ps_3_0" );
					goto case 2;

				case 2:
					if ( ps2x )
					{
						rsc.AddShaderProfile( "ps_2_x" );
					}
					if ( ps2a )
					{
						rsc.AddShaderProfile( "ps_2_a" );
					}
					if ( ps2b )
					{
						rsc.AddShaderProfile( "ps_2_b" );
					}

					rsc.AddShaderProfile( "ps_2_0" );
					goto case 1;

				case 1:
					if ( major > 1 || minor >= 4 )
					{
						rsc.AddShaderProfile( "ps_1_4" );
					}
					if ( major > 1 || minor >= 3 )
					{
						rsc.AddShaderProfile( "ps_1_3" );
					}
					if ( major > 1 || minor >= 2 )
					{
						rsc.AddShaderProfile( "ps_1_2" );
					}

					rsc.AddShaderProfile( "ps_1_1" );
					rsc.SetCapability( Graphics.Capabilities.FragmentPrograms );
					break;
			}
		}
		public override RenderSystemCapabilities CreateRenderSystemCapabilities()
		{
			var rsc = new RenderSystemCapabilities();

			rsc.SetCategoryRelevant( CapabilitiesCategory.GL, true );
			rsc.DriverVersion = driverVersion;

			string deviceName = GL.GetString( All.Renderer );
			GLES2Config.GlCheckError( this );
			string vendorName = GL.GetString( All.Vendor );
			GLES2Config.GlCheckError( this );

			deviceName = deviceName ?? string.Empty;
			vendorName = vendorName ?? string.Empty;

			if ( !string.IsNullOrEmpty( deviceName ) )
			{
				rsc.DeviceName = deviceName;
			}

			rsc.RendersystemName = this.Name;

			//Determine vendor
			if ( vendorName.Contains( "Imagination Technologies" ) )
			{
				rsc.Vendor = GPUVendor.ImaginationTechnologies;
			}
			else if ( vendorName.Contains( "Apple Computer, Inc." ) )
			{
				rsc.Vendor = GPUVendor.Apple; // iOS Simulator
			}
			else if ( vendorName.Contains( "NVIDIA" ) )
			{
				rsc.Vendor = GPUVendor.Nvidia;
			}
			else
			{
				rsc.Vendor = GPUVendor.Unknown;
			}

			//Multitexturing support and set number of texture units;

			int units = 0;
			GL.GetInteger( All.MaxTextureImageUnits, ref units );
			GLES2Config.GlCheckError( this );
			rsc.TextureUnitCount = units;

			//check hardware stenicl support and set bit depth
			int stencil = -1;
			GL.GetInteger( All.StencilBits, ref stencil );
			GLES2Config.GlCheckError( this );

			if ( stencil != -1 )
			{
				rsc.SetCapability( Graphics.Capabilities.StencilBuffer );
				rsc.SetCapability( Graphics.Capabilities.TwoSidedStencil );
				rsc.StencilBufferBitCount = stencil;
			}

			// Scissor test is standard
			rsc.SetCapability( Graphics.Capabilities.ScissorTest );

			//Vertex buffer objects are always supported by OpenGL ES
			/*Port notes: Ogre sets capability as VBO, or Vertex Buffer Objects. 
			  VertexBuffer is closest  
			 */
			rsc.SetCapability( Graphics.Capabilities.VertexBuffer );

			//Check for hardware occlusion support
			if ( this.glSupport.CheckExtension( "GL_EXT_occlusion_query_boolean" ) )
			{
				;
				rsc.SetCapability( Graphics.Capabilities.HardwareOcculusion );
			}

			// OpenGL ES - Check for these extensions too
			// For 2.0, http://www.khronos.org/registry/gles/api/2.0/gl2ext.h

			if ( this.glSupport.CheckExtension( "GL_IMG_texture_compression_pvrtc" ) || this.glSupport.CheckExtension( "GL_EXT_texture_compression_dxt1" ) || this.glSupport.CheckExtension( "GL_EXT_texture_compression_s3tc" ) )
			{
				rsc.SetCapability( Graphics.Capabilities.TextureCompression );

				if ( this.glSupport.CheckExtension( "GL_IMG_texture_compression_pvrtc" ) )
				{
					rsc.SetCapability( Graphics.Capabilities.TextureCompressionPVRTC );
				}

				if ( this.glSupport.CheckExtension( "GL_EXT_texture_compression_dxt1" ) && this.glSupport.CheckExtension( "GL_EXT_texture_compression_s3tc" ) )
				{
					rsc.SetCapability( Graphics.Capabilities.TextureCompressionDXT );
				}
			}

			if ( this.glSupport.CheckExtension( "GL_EXT_texture_filter_anisotropic" ) )
			{
				rsc.SetCapability( Graphics.Capabilities.AnisotropicFiltering );
			}

			rsc.SetCapability( Graphics.Capabilities.FrameBufferObjects );
			rsc.SetCapability( Graphics.Capabilities.HardwareRenderToTexture );
			rsc.MultiRenderTargetCount = 1;

			//Cube map
			rsc.SetCapability( Graphics.Capabilities.CubeMapping );

			//Stencil wrapping
			rsc.SetCapability( Graphics.Capabilities.StencilWrap );

			//GL always shares vertex and fragment texture units (for now?)
			rsc.VertexTextureUnitsShared = true;

			//Hardware support mipmapping
			//rsc.SetCapability(Graphics.Capabilities.AutoMipMap);

			//Blending support
			rsc.SetCapability( Graphics.Capabilities.Blending );
			rsc.SetCapability( Graphics.Capabilities.AdvancedBlendOperations );

			//DOT3 support is standard
			rsc.SetCapability( Graphics.Capabilities.Dot3 );

			//Point size
			var psRange = new float[ 2 ] { 0.0f, 0.0f };
			GL.GetFloat( All.AliasedPointSizeRange, psRange );
			GLES2Config.GlCheckError( this );
			rsc.MaxPointSize = psRange[ 1 ];

			//Point sprites
			rsc.SetCapability( Graphics.Capabilities.PointSprites );
			rsc.SetCapability( Graphics.Capabilities.PointExtendedParameters );

			// GLSL ES is always supported in GL ES 2
			rsc.AddShaderProfile( "glsles" );
			LogManager.Instance.Write( "GLSL ES support detected" );

			//todo: OGRE has a #if here checking for cg support
			//I believe Android supports cg, but not iPhone?
			rsc.AddShaderProfile( "cg" );
			rsc.AddShaderProfile( "ps_2_0" );
			rsc.AddShaderProfile( "vs_2_0" );

			//UBYTE4 is always supported
			rsc.SetCapability( Graphics.Capabilities.VertexFormatUByte4 );

			//Infinite far plane always supported
			rsc.SetCapability( Graphics.Capabilities.InfiniteFarPlane );

			//Vertex/Fragment programs
			rsc.SetCapability( Graphics.Capabilities.VertexPrograms );
			rsc.SetCapability( Graphics.Capabilities.FragmentPrograms );

			//Sepearte shader objects
			if ( glSupport.CheckExtension( "GL_EXT_seperate_shader_objects" ) )
			    rsc.SetCapability( Graphics.Capabilities.SeperateShaderObjects );

			float floatConstantCount = 0;
			GL.GetFloat( All.MaxVertexUniformVectors, ref floatConstantCount );
			GLES2Config.GlCheckError( this );
			rsc.VertexProgramConstantFloatCount = (int) floatConstantCount;
			rsc.VertexProgramConstantBoolCount = (int) floatConstantCount;
			rsc.VertexProgramConstantIntCount = (int) floatConstantCount;

			//Fragment Program Properties
			floatConstantCount = 0;
			GL.GetFloat( All.MaxFragmentUniformVectors, ref floatConstantCount );
			GLES2Config.GlCheckError( this );
			rsc.FragmentProgramConstantFloatCount = (int) floatConstantCount;
			rsc.FragmentProgramConstantBoolCount = (int) floatConstantCount;
			rsc.FragmentProgramConstantIntCount = (int) floatConstantCount;

			//Geometry programs are not supported, report 0
			rsc.GeometryProgramConstantFloatCount = 0;
			rsc.GeometryProgramConstantBoolCount = 0;
			rsc.GeometryProgramConstantIntCount = 0;

			//Check for Float textures
			rsc.SetCapability( Graphics.Capabilities.TextureFloat );

			//Alpha to coverate always 'supported' when MSAA is availalbe
			//although card may ignore it if it doesn't specifically support A2C
			rsc.SetCapability( Graphics.Capabilities.AlphaToCoverage );

			//No point sprites, so no size
			rsc.MaxPointSize = 0;

			if ( this.glSupport.CheckExtension( "GL_OES_get_program_binary" ) )
			{
				// http://www.khronos.org/registry/gles/extensions/OES/OES_get_program_binary.txt
				rsc.SetCapability( Graphics.Capabilities.CanGetCompiledShaderBuffer );
			}

			return rsc;
		}
        private void _convertVertexShaderCaps(RenderSystemCapabilities rsc)
        {
            var major     = 0xFF;
            var minor     = 0xFF;
            var minVsCaps = new D3D9.Capabilities();

            // Find the device with the lowest vertex shader caps.
            foreach (var pCurDriver in this._driverList)
            {
                var rkCurCaps = pCurDriver.D3D9DeviceCaps;
                var currMajor = rkCurCaps.VertexShaderVersion.Major;
                var currMinor = rkCurCaps.VertexShaderVersion.Minor;

                if (currMajor < major)
                {
                    major     = currMajor;
                    minor     = currMinor;
                    minVsCaps = rkCurCaps;
                }
                else if (currMajor == major && currMinor < minor)
                {
                    minor     = currMinor;
                    minVsCaps = rkCurCaps;
                }
            }

            var vs2x = false;
            var vs2a = false;

            // Special case detection for vs_2_x/a support
            if (major >= 2)
            {
                if ((minVsCaps.VS20Caps.Caps & D3D9.VertexShaderCaps.Predication) != 0 &&
                    (minVsCaps.VS20Caps.DynamicFlowControlDepth > 0) && (minVsCaps.VS20Caps.TempCount >= 12))
                {
                    vs2x = true;
                }

                if ((minVsCaps.VS20Caps.Caps & D3D9.VertexShaderCaps.Predication) != 0 &&
                    (minVsCaps.VS20Caps.DynamicFlowControlDepth > 0) && (minVsCaps.VS20Caps.TempCount >= 13))
                {
                    vs2a = true;
                }
            }

            // Populate max param count
            switch (major)
            {
            case 1:
                // No boolean params allowed
                rsc.VertexProgramConstantBoolCount = 0;
                // No integer params allowed
                rsc.VertexProgramConstantIntCount = 0;
                // float params, always 4D
                rsc.VertexProgramConstantFloatCount = minVsCaps.MaxVertexShaderConst;
                break;

            case 2:
                // 16 boolean params allowed
                rsc.VertexProgramConstantBoolCount = 16;
                // 16 integer params allowed, 4D
                rsc.VertexProgramConstantIntCount = 16;
                // float params, always 4D
                rsc.VertexProgramConstantFloatCount = minVsCaps.MaxVertexShaderConst;
                break;

            case 3:
                // 16 boolean params allowed
                rsc.VertexProgramConstantBoolCount = 16;
                // 16 integer params allowed, 4D
                rsc.VertexProgramConstantIntCount = 16;
                // float params, always 4D
                rsc.VertexProgramConstantFloatCount = minVsCaps.MaxVertexShaderConst;
                break;
            }

            // populate syntax codes in program manager (no breaks in this one so it falls through)
            switch (major)
            {
            case 3:
                rsc.AddShaderProfile("vs_3_0");
                goto case 2;

            case 2:
                if (vs2x)
                {
                    rsc.AddShaderProfile("vs_2_x");
                }
                if (vs2a)
                {
                    rsc.AddShaderProfile("vs_2_a");
                }

                rsc.AddShaderProfile("vs_2_0");
                goto case 1;

            case 1:
                rsc.AddShaderProfile("vs_1_1");
                rsc.SetCapability(Graphics.Capabilities.VertexPrograms);
                break;
            }
        }
        private void _convertPixelShaderCaps(RenderSystemCapabilities rsc)
        {
            var major     = 0xFF;
            var minor     = 0xFF;
            var minPsCaps = new D3D9.Capabilities();

            // Find the device with the lowest vertex shader caps.
            foreach (var pCurDriver in this._driverList)
            {
                var currCaps  = pCurDriver.D3D9DeviceCaps;
                var currMajor = currCaps.PixelShaderVersion.Major;
                var currMinor = currCaps.PixelShaderVersion.Minor;

                if (currMajor < major)
                {
                    major     = currMajor;
                    minor     = currMinor;
                    minPsCaps = currCaps;
                }
                else if (currMajor == major && currMinor < minor)
                {
                    minor     = currMinor;
                    minPsCaps = currCaps;
                }
            }

            var ps2a = false;
            var ps2b = false;
            var ps2x = false;

            // Special case detection for ps_2_x/a/b support
            if (major >= 2)
            {
                if ((minPsCaps.PS20Caps.Caps & D3D9.PixelShaderCaps.NoTextureInstructionLimit) != 0 &&
                    (minPsCaps.PS20Caps.TempCount >= 32))
                {
                    ps2b = true;
                }

                if ((minPsCaps.PS20Caps.Caps & D3D9.PixelShaderCaps.NoTextureInstructionLimit) != 0 &&
                    (minPsCaps.PS20Caps.Caps & D3D9.PixelShaderCaps.NoDependentReadLimit) != 0 &&
                    (minPsCaps.PS20Caps.Caps & D3D9.PixelShaderCaps.ArbitrarySwizzle) != 0 &&
                    (minPsCaps.PS20Caps.Caps & D3D9.PixelShaderCaps.GradientInstructions) != 0 &&
                    (minPsCaps.PS20Caps.Caps & D3D9.PixelShaderCaps.Predication) != 0 && (minPsCaps.PS20Caps.TempCount >= 22))
                {
                    ps2a = true;
                }

                // Does this enough?
                if (ps2a || ps2b)
                {
                    ps2x = true;
                }
            }

            switch (major)
            {
            case 1:
                // no boolean params allowed
                rsc.FragmentProgramConstantBoolCount = 0;
                // no integer params allowed
                rsc.FragmentProgramConstantIntCount = 0;
                // float params, always 4D
                // NB in ps_1_x these are actually stored as fixed point values,
                // but they are entered as floats
                rsc.FragmentProgramConstantFloatCount = 8;
                break;

            case 2:
                // 16 boolean params allowed
                rsc.FragmentProgramConstantBoolCount = 16;
                // 16 integer params allowed, 4D
                rsc.FragmentProgramConstantIntCount = 16;
                // float params, always 4D
                rsc.FragmentProgramConstantFloatCount = 32;
                break;

            case 3:
                // 16 boolean params allowed
                rsc.FragmentProgramConstantBoolCount = 16;
                // 16 integer params allowed, 4D
                rsc.FragmentProgramConstantIntCount = 16;
                // float params, always 4D
                rsc.FragmentProgramConstantFloatCount = 224;
                break;
            }

            // populate syntax codes in program manager (no breaks in this one so it falls through)
            switch (major)
            {
            case 3:
                if (minor > 0)
                {
                    rsc.AddShaderProfile("ps_3_x");
                }

                rsc.AddShaderProfile("ps_3_0");
                goto case 2;

            case 2:
                if (ps2x)
                {
                    rsc.AddShaderProfile("ps_2_x");
                }
                if (ps2a)
                {
                    rsc.AddShaderProfile("ps_2_a");
                }
                if (ps2b)
                {
                    rsc.AddShaderProfile("ps_2_b");
                }

                rsc.AddShaderProfile("ps_2_0");
                goto case 1;

            case 1:
                if (major > 1 || minor >= 4)
                {
                    rsc.AddShaderProfile("ps_1_4");
                }
                if (major > 1 || minor >= 3)
                {
                    rsc.AddShaderProfile("ps_1_3");
                }
                if (major > 1 || minor >= 2)
                {
                    rsc.AddShaderProfile("ps_1_2");
                }

                rsc.AddShaderProfile("ps_1_1");
                rsc.SetCapability(Graphics.Capabilities.FragmentPrograms);
                break;
            }
        }
		private void _setCapabilitiesForReachProfile( ref RenderSystemCapabilities rsc )
		{
			// Fill in the Reach profile requirements.
			// Texture Compression
			// We always support compression, Xna will decompress if device does not support
			rsc.SetCapability( Graphics.Capabilities.TextureCompression );
			rsc.SetCapability( Graphics.Capabilities.TextureCompressionDXT );

			// Xna uses vertex buffers for everything
			rsc.SetCapability( Graphics.Capabilities.VertexBuffer );

			//VertexShaderVersion = 0x200;
			rsc.SetCapability( Graphics.Capabilities.VertexPrograms );
			rsc.MaxVertexProgramVersion = "vs_2_0";
			rsc.VertexProgramConstantIntCount = 16 * 4;
			rsc.VertexProgramConstantFloatCount = 256;
			rsc.AddShaderProfile( "vs_1_1" );
			rsc.AddShaderProfile( "vs_2_0" );

			//PixelShaderVersion = 0x200;
			rsc.SetCapability( Graphics.Capabilities.FragmentPrograms );
			rsc.MaxFragmentProgramVersion = "ps_2_0";
			rsc.FragmentProgramConstantIntCount = 0;
			rsc.FragmentProgramConstantFloatCount = 32;
			rsc.AddShaderProfile( "ps_1_1" );
			rsc.AddShaderProfile( "ps_1_2" );
			rsc.AddShaderProfile( "ps_1_3" );
			rsc.AddShaderProfile( "ps_1_4" );
			rsc.AddShaderProfile( "ps_2_0" );

			//SeparateAlphaBlend = false;
			//DestBlendSrcAlphaSat = false;

			//MaxPrimitiveCount = 65535;
			//IndexElementSize32 = false;
			//MaxVertexStreams = 16;
			//MaxStreamStride = 255;

			//MaxTextureSize = 2048;
			//MaxCubeSize = 512;
			//MaxVolumeExtent = 0;
			//MaxTextureAspectRatio = 2048;
			//MaxVertexSamplers = 0;
			//MaxRenderTargets = 1;
			rsc.TextureUnitCount = 16;
			rsc.MultiRenderTargetCount = 1;

			//NonPow2Unconditional = false;
			//NonPow2Cube = false;
			//NonPow2Volume = false;

			//ValidTextureFormats       = MakeList(STANDARD_TEXTURE_FORMATS, COMPRESSED_TEXTURE_FORMATS, SIGNED_TEXTURE_FORMATS);
			//ValidCubeFormats          = MakeList(STANDARD_TEXTURE_FORMATS, COMPRESSED_TEXTURE_FORMATS);
			//ValidVolumeFormats        = MakeList<SurfaceFormat>();
			//ValidVertexTextureFormats = MakeList<SurfaceFormat>();
			//InvalidFilterFormats      = MakeList<SurfaceFormat>();
			//InvalidBlendFormats       = MakeList<SurfaceFormat>();
			//ValidVertexFormats        = MakeList(STANDARD_VERTEX_FORMATS);
		}
		private void _setCapabilitiesForHiDefProfile( ref RenderSystemCapabilities rsc )
		{
			// Fill in the HiDef profile requirements.
			rsc.SetCapability( Graphics.Capabilities.HardwareOcculusion );

			//VertexShaderVersion = 0x300;
			rsc.SetCapability( Graphics.Capabilities.VertexPrograms );
			rsc.MaxVertexProgramVersion = "vs_3_0";
			rsc.VertexProgramConstantIntCount = 16 * 4;
			rsc.VertexProgramConstantFloatCount = 256;
			rsc.AddShaderProfile( "vs_1_1" );
			rsc.AddShaderProfile( "vs_2_0" );
			rsc.AddShaderProfile( "vs_2_x" );
			rsc.AddShaderProfile( "vs_3_0" );

			//PixelShaderVersion = 0x300;
			rsc.SetCapability( Graphics.Capabilities.FragmentPrograms );
			rsc.MaxFragmentProgramVersion = "ps_3_0";
			rsc.FragmentProgramConstantIntCount = 16;
			rsc.FragmentProgramConstantFloatCount = 224;
			rsc.AddShaderProfile( "ps_1_1" );
			rsc.AddShaderProfile( "ps_1_2" );
			rsc.AddShaderProfile( "ps_1_3" );
			rsc.AddShaderProfile( "ps_1_4" );
			rsc.AddShaderProfile( "ps_2_0" );
			rsc.AddShaderProfile( "ps_3_0" );

			//SeparateAlphaBlend = true;
			rsc.SetCapability( Graphics.Capabilities.AdvancedBlendOperations );
			//DestBlendSrcAlphaSat = true;

			//MaxPrimitiveCount = 1048575;
			//IndexElementSize32 = true;
			//MaxVertexStreams = 16;
			//MaxStreamStride = 255;

			//MaxTextureSize = 4096;
			//MaxCubeSize = 4096;
			//MaxVolumeExtent = 256;
			//MaxTextureAspectRatio = 2048;
			//MaxVertexSamplers = 4;
			//MaxRenderTargets = 4;
			rsc.TextureUnitCount = 16;
			rsc.MultiRenderTargetCount = 4;

			//NonPow2Unconditional = true;
			//NonPow2Cube = true;
			//NonPow2Volume = true;

			//ValidTextureFormats       = MakeList(STANDARD_TEXTURE_FORMATS, COMPRESSED_TEXTURE_FORMATS, SIGNED_TEXTURE_FORMATS, HIDEF_TEXTURE_FORMATS, FLOAT_TEXTURE_FORMATS);
			//ValidCubeFormats          = MakeList(STANDARD_TEXTURE_FORMATS, COMPRESSED_TEXTURE_FORMATS, HIDEF_TEXTURE_FORMATS, FLOAT_TEXTURE_FORMATS);
			//ValidVolumeFormats        = MakeList(STANDARD_TEXTURE_FORMATS, HIDEF_TEXTURE_FORMATS, FLOAT_TEXTURE_FORMATS);
			//ValidVertexTextureFormats = MakeList(FLOAT_TEXTURE_FORMATS);
			//InvalidFilterFormats      = MakeList(FLOAT_TEXTURE_FORMATS);
			//InvalidBlendFormats       = MakeList(STANDARD_FLOAT_TEXTURE_FORMATS);
			//ValidVertexFormats        = MakeList(STANDARD_VERTEX_FORMATS, HIDEF_VERTEX_FORMATS);
		}