module Graphics.LambdaCube.RenderSystem.GL.Capabilities where
import qualified Data.Set as Set
import Graphics.Rendering.OpenGL.Raw.Core31
import qualified Graphics.Rendering.OpenGL.Raw.ARB.Compatibility as Compat
import Graphics.LambdaCube.RenderSystemCapabilities
import Graphics.LambdaCube.RenderSystem.GL.Utils
mkGLCapabilities :: IO RenderSystemCapabilities
mkGLCapabilities = do
vendorS <- getString gl_VENDOR
extSList <- getGLExtensions
deviceName <- getString gl_RENDERER
let v = words vendorS
vendorName = if elem "NVIDIA" v then GPU_NVIDIA
else if elem "ATI" v then GPU_ATI
else if elem "Intel" v then GPU_INTEL
else if elem "S3" v then GPU_S3
else if elem "Matrox" v then GPU_MATROX
else if elem "3DLabs" v then GPU_3DLABS
else if elem "SiS" v then GPU_SIS
else GPU_UNKNOWN
(major,minor) <- getGLVersion
let ext = Set.fromList extSList
glVer a b = major > a || (major >= a && minor >= b)
supports s = Set.member s ext
driverVersion = DriverVersion (fromIntegral major) (fromIntegral minor) 0 0
caps0 =
[ RSC_FIXED_FUNCTION
, RSC_SCISSOR_TEST
, RSC_USER_CLIP_PLANES
, RSC_VERTEX_FORMAT_UBYTE4
, RSC_INFINITE_FAR_PLANE
, RSC_TEXTURE_3D
]
caps1 = if not (glVer 1 4 || supports "GL_SGIS_generate_mipmap") then [] else
[RSC_AUTOMIPMAP]
caps2 = if (glVer 1 3 || supports "GL_ARB_texture_env_combine" || supports "GL_EXT_texture_env_combine") then [RSC_BLENDING] else []
numTexUnits <- case glVer 1 3 || supports "GL_ARB_multitexture" of
True -> do
mtimu <- case supports "GL_ARB_fragment_program" of
{ True -> do
getInteger gl_MAX_TEXTURE_IMAGE_UNITS
; False -> return 0
}
return mtimu
False -> return 1
let caps3 = if (supports "GL_EXT_texture_filter_anisotropic") then [RSC_ANISOTROPY] else []
caps4 = if (glVer 1 3 || supports "GL_ARB_texture_env_dot3" || supports "GL_EXT_texture_env_dot3") then [RSC_DOT3] else []
caps5 = if (glVer 1 3 || supports "GL_ARB_texture_cube_map" || supports "GL_EXT_texture_cube_map") then [RSC_CUBEMAPPING] else []
caps6 = if (glVer 2 0 || supports "GL_ARB_point_sprite") then [RSC_POINT_SPRITES] else []
caps7 = if (glVer 1 4) then [RSC_POINT_EXTENDED_PARAMETERS] else []
caps8 = if (supports "GL_ARB_point_parameters") then [RSC_POINT_EXTENDED_PARAMETERS_ARB] else []
caps9 = if (supports "GL_EXT_point_parameters") then [RSC_POINT_EXTENDED_PARAMETERS_EXT] else []
stencilBits <- getInteger Compat.gl_STENCIL_BITS
let caps10 = if stencilBits > 0 then [RSC_HWSTENCIL] else []
caps11 = if not (glVer 1 5 || supports "GL_ARB_vertex_buffer_object") then [] else
[RSC_VBO] ++ (if not (supports "GL_ARB_vertex_buffer_object") then [RSC_GL1_5_NOVBO] else [])
(prof1,caps12) = if supports "GL_NV_register_combiners2" && supports "GL_NV_texture_shader" then (["fp20"],[RSC_FRAGMENT_PROGRAM]) else ([],[])
(prof2,caps13,fragConstBool,fragConstInt,fragConstFloat) = if supports "GL_ATI_fragment_shader" then (["ps_1_4","ps_1_3","ps_1_2","ps_1_1"],[RSC_FRAGMENT_PROGRAM],0,0,8) else ([],[],0,0,0)
prof3 = if glVer 2 0 ||
(supports "GL_ARB_shading_language_100"
&& supports "GL_ARB_shader_objects"
&& supports "GL_ARB_fragment_shader"
&& supports "GL_ARB_vertex_shader") then ["glsl"] else []
caps14 = if (glVer 2 0 && supports "GL_NV_transform_feedback") then [RSC_HWRENDER_TO_VERTEX_BUFFER] else []
caps15 = if not (glVer 1 3 || supports "GL_ARB_texture_compression") then [] else
[RSC_TEXTURE_COMPRESSION]
++ (if supports "GL_EXT_texture_compression_s3tc" then [RSC_TEXTURE_COMPRESSION_DXT] else [])
++ (if supports "GL_NV_texture_compression_vtc" then [RSC_TEXTURE_COMPRESSION_VTC] else [])
caps16 = if (glVer 2 0 || supports "GL_EXT_stencil_two_side") then [RSC_TWO_SIDED_STENCIL] else []
caps17 = if (glVer 1 4 || supports "GL_EXT_stencil_wrap") then [RSC_STENCIL_WRAP] else []
caps18 = case glVer 1 5 || supports "GL_ARB_occlusion_query" of
{ True -> [RSC_HWOCCLUSION] ++ (if not (supports "GL_ARB_occlusion_query") then [RSC_GL1_5_NOHWOCCLUSION] else [])
; False -> if supports "GL_NV_occlusion_query" then [RSC_HWOCCLUSION] else []
}
caps19 = if (supports "GL_ARB_texture_non_power_of_two") then [RSC_NON_POWER_OF_2_TEXTURES] else []
caps20 = if (supports "GL_ATI_texture_float" || supports "GL_ARB_texture_float") then [RSC_TEXTURE_FLOAT] else []
(numMTR,caps21) <- case supports "GL_EXT_framebuffer_object" of
True -> do
(n,c) <- case glVer 2 0 || supports "GL_ARB_draw_buffers" || supports "GL_ATI_draw_buffers" of
True -> do
m <- getInteger gl_MAX_DRAW_BUFFERS
let cp = case (glVer 2 0, supports "GL_ARB_draw_buffers", supports "GL_ATI_draw_buffers") of
(False,True,True) -> [RSC_FBO_ARB,RSC_FBO_ATI]
(False,True,False) -> [RSC_FBO_ARB]
(False,False,True) -> [RSC_FBO_ATI]
_ -> []
return (m,[RSC_MRT_DIFFERENT_BIT_DEPTHS,RSC_FBO] ++ cp)
False -> return (0,[])
return (n,RSC_HWRENDER_TO_TEXTURE:c)
False -> do
return (0,[])
maxPointSize <- getFloat Compat.gl_POINT_SIZE_MAX
(numVertTexUnits,caps22,vertTexUnitsShared) <- case supports "GL_ARB_vertex_shader" of
True -> do
vunits <- getInteger gl_MAX_VERTEX_TEXTURE_IMAGE_UNITS
return (vunits,if vunits > 0 then [RSC_VERTEX_TEXTURE_FETCH] else [], True)
False -> return (0,[],False)
let caps23 = if (glVer 1 4 || supports "GL_EXT_texture_lod_bias") then [RSC_MIPMAP_LOD_BIAS] else []
caps24 = if (supports "GL_ARB_multisample") then [RSC_ALPHA_TO_COVERAGE] else []
caps25 = if (glVer 2 0) then [RSC_ADVANCED_BLEND_OPERATIONS] else []
return RenderSystemCapabilities
{ rscDriverVersion = driverVersion
, rscVendor = vendorName
, rscNumTextureUnits = fromIntegral numTexUnits
, rscStencilBufferBitDepth = fromIntegral stencilBits
, rscCapabilities = Set.fromList $ caps0 ++ caps1 ++ caps2 ++ caps3 ++ caps4 ++ caps5 ++ caps6 ++ caps7 ++ caps8 ++ caps9
++ caps10 ++ caps11 ++ caps12 ++ caps13 ++ caps14 ++ caps15 ++ caps16 ++ caps17 ++ caps18 ++ caps19
++ caps20 ++ caps21 ++ caps22 ++ caps23 ++ caps24 ++ caps25
, rscDeviceName = deviceName
, rscRenderSystemName = "OpenGL Rendering Subsystem"
, rscVertexProgramConstantFloatCount = undefined
, rscVertexProgramConstantIntCount = undefined
, rscVertexProgramConstantBoolCount = undefined
, rscGeometryProgramConstantFloatCount = undefined
, rscGeometryProgramConstantIntCount = undefined
, rscGeometryProgramConstantBoolCount = undefined
, rscFragmentProgramConstantFloatCount = fragConstFloat
, rscFragmentProgramConstantIntCount = fragConstInt
, rscFragmentProgramConstantBoolCount = fragConstBool
, rscNumMultiRenderTargets = fromIntegral numMTR
, rscMaxPointSize = realToFrac maxPointSize
, rscNonPOW2TexturesLimited = False
, rscNumVertexTextureUnits = fromIntegral numVertTexUnits
, rscVertexTextureUnitsShared = vertTexUnitsShared
, rscGeometryProgramNumOutputVertices = undefined
, rscSupportedShaderProfiles = Set.fromList $ prof1 ++ prof2 ++ prof3
}