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
_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 ( _fixedFunctionTextureUnits > maxTexCoords )
{
_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 ) )
{
_hardwareBufferManager = new GLHardwareBufferManager();
}
else
{
_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
gpuProgramMgr = new GLGpuProgramManager();
if ( caps.HasCapability( Graphics.Capabilities.VertexPrograms ) )
{
if ( caps.IsShaderProfileSupported( "arbvp1" ) )
{
gpuProgramMgr.RegisterProgramFactory( "arbvp1", new ARBGpuProgramFactory() );
}
if ( caps.IsShaderProfileSupported( "vp30" ) )
{
gpuProgramMgr.RegisterProgramFactory( "vp30", new ARBGpuProgramFactory() );
}
if ( caps.IsShaderProfileSupported( "vp40" ) )
{
gpuProgramMgr.RegisterProgramFactory( "vp40", new ARBGpuProgramFactory() );
}
if ( caps.IsShaderProfileSupported( "gp4vp" ) )
{
gpuProgramMgr.RegisterProgramFactory( "gp4vp", new ARBGpuProgramFactory() );
}
if ( caps.IsShaderProfileSupported( "gpu_vp" ) )
{
gpuProgramMgr.RegisterProgramFactory( "gpu_vp", new ARBGpuProgramFactory() );
}
}
if ( caps.HasCapability( Graphics.Capabilities.GeometryPrograms ) )
{
//TODO : Should these be createGLArbGpuProgram or createGLGpuNVparseProgram?
if ( caps.IsShaderProfileSupported( "nvgp4" ) )
{
gpuProgramMgr.RegisterProgramFactory( "nvgp4", new ARBGpuProgramFactory() );
}
if ( caps.IsShaderProfileSupported( "gp4gp" ) )
{
gpuProgramMgr.RegisterProgramFactory( "gp4gp", new ARBGpuProgramFactory() );
}
if ( caps.IsShaderProfileSupported( "gpu_gp" ) )
{
gpuProgramMgr.RegisterProgramFactory( "gpu_gp", new ARBGpuProgramFactory() );
}
}
if ( caps.HasCapability( Graphics.Capabilities.FragmentPrograms ) )
{
if ( caps.IsShaderProfileSupported( "fp20" ) )
{
gpuProgramMgr.RegisterProgramFactory( "fp20", new Nvidia.NvparseProgramFactory() );
}
if ( caps.IsShaderProfileSupported( "ps_1_4" ) )
{
gpuProgramMgr.RegisterProgramFactory( "ps_1_4", new ATI.ATIFragmentShaderFactory() );
}
if ( caps.IsShaderProfileSupported( "ps_1_3" ) )
{
gpuProgramMgr.RegisterProgramFactory( "ps_1_3", new ATI.ATIFragmentShaderFactory() );
}
if ( caps.IsShaderProfileSupported( "ps_1_2" ) )
{
gpuProgramMgr.RegisterProgramFactory( "ps_1_2", new ATI.ATIFragmentShaderFactory() );
}
if ( caps.IsShaderProfileSupported( "ps_1_1" ) )
{
gpuProgramMgr.RegisterProgramFactory( "ps_1_1", new ATI.ATIFragmentShaderFactory() );
}
if ( caps.IsShaderProfileSupported( "arbfp1" ) )
{
gpuProgramMgr.RegisterProgramFactory( "arbfp1", new ARBGpuProgramFactory() );
}
if ( caps.IsShaderProfileSupported( "fp40" ) )
{
gpuProgramMgr.RegisterProgramFactory( "fp40", new ARBGpuProgramFactory() );
}
if ( caps.IsShaderProfileSupported( "fp30" ) )
{
gpuProgramMgr.RegisterProgramFactory( "fp30", new ARBGpuProgramFactory() );
}
}
if ( caps.IsShaderProfileSupported( "glsl" ) )
{
// NFZ - check for GLSL vertex and fragment shader support successful
_GLSLProgramFactory = new GLSL.GLSLProgramFactory();
HighLevelGpuProgramManager.Instance.AddFactory( _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)");
rttManager = new GLFBORTTManager(_glSupport, false);
caps.SetCapability(Graphics.Capabilities.RTTSerperateDepthBuffer);
//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
rttManager = new GLPBRTTManager( _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
rttManager = new GLCopyingRTTManager(_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(_glSupport);
_glInitialised = true;
}