module Graphics.Rendering.OpenGL.GL.Shaders.ProgramObjects (
Program, createProgram, programDeleteStatus,
attachShader, detachShader, attachedShaders,
linkProgram, linkStatus,
validateProgram, validateStatus,
programInfoLog,
currentProgram,
programSeparable, programBinaryRetrievableHint,
bindFragDataLocation, getFragDataLocation
) where
import Data.List
import Data.Maybe
import Data.StateVar
import Foreign.Marshal.Array
import Foreign.Ptr
import Graphics.Rendering.OpenGL.GL.ByteString
import Graphics.Rendering.OpenGL.GL.Framebuffer
import Graphics.Rendering.OpenGL.GL.GLboolean
import Graphics.Rendering.OpenGL.GL.QueryUtils
import Graphics.Rendering.OpenGL.GL.Shaders.Program
import Graphics.Rendering.OpenGL.GL.Shaders.Shader
import Graphics.GL
createProgram :: IO Program
createProgram = fmap Program glCreateProgram
attachShader :: Program -> Shader -> IO ()
attachShader p s = glAttachShader (programID p) (shaderID s)
detachShader :: Program -> Shader -> IO ()
detachShader p s = glDetachShader (programID p) (shaderID s)
attachedShaders :: Program -> StateVar [Shader]
attachedShaders program =
makeStateVar (getAttachedShaders program) (setAttachedShaders program)
getAttachedShaders :: Program -> IO [Shader]
getAttachedShaders program = do
numShaders <- get (numAttachedShaders program)
ids <- allocaArray (fromIntegral numShaders) $ \buf -> do
glGetAttachedShaders (programID program) numShaders nullPtr buf
peekArray (fromIntegral numShaders) buf
return $ map Shader ids
setAttachedShaders :: Program -> [Shader] -> IO ()
setAttachedShaders program newShaders = do
currentShaders <- getAttachedShaders program
mapM_ (attachShader program) (newShaders \\ currentShaders)
mapM_ (detachShader program) (currentShaders \\ newShaders)
linkProgram :: Program -> IO ()
linkProgram = glLinkProgram . programID
currentProgram :: StateVar (Maybe Program)
currentProgram =
makeStateVar
(do p <- fmap Program $ getInteger1 fromIntegral GetCurrentProgram
return $ if p == noProgram then Nothing else Just p)
(glUseProgram . programID . fromMaybe noProgram)
noProgram :: Program
noProgram = Program 0
validateProgram :: Program -> IO ()
validateProgram = glValidateProgram . programID
programInfoLog :: Program -> GettableStateVar String
programInfoLog =
makeGettableStateVar .
fmap unpackUtf8 .
stringQuery programInfoLogLength (glGetProgramInfoLog . programID)
programSeparable :: Program -> StateVar Bool
programSeparable = programStateVarBool ProgramSeparable
programBinaryRetrievableHint :: Program -> StateVar Bool
programBinaryRetrievableHint = programStateVarBool ProgramBinaryRetrievableHint
programStateVarBool :: GetProgramPName -> Program -> StateVar Bool
programStateVarBool pname program =
makeStateVar
(get (programVar1 unmarshalGLboolean pname program))
(glProgramParameteri (programID program)
(marshalGetProgramPName pname) . marshalGLboolean)
programDeleteStatus :: Program -> GettableStateVar Bool
programDeleteStatus = programVar1 unmarshalGLboolean ProgramDeleteStatus
linkStatus :: Program -> GettableStateVar Bool
linkStatus = programVar1 unmarshalGLboolean LinkStatus
validateStatus :: Program -> GettableStateVar Bool
validateStatus = programVar1 unmarshalGLboolean ValidateStatus
programInfoLogLength :: Program -> GettableStateVar GLsizei
programInfoLogLength = programVar1 fromIntegral ProgramInfoLogLength
numAttachedShaders :: Program -> GettableStateVar GLsizei
numAttachedShaders = programVar1 fromIntegral AttachedShaders
bindFragDataLocation :: Program -> String -> SettableStateVar DrawBufferIndex
bindFragDataLocation (Program program) varName = makeSettableStateVar $ \ind ->
withGLstring varName $ glBindFragDataLocation program ind
getFragDataLocation :: Program -> String -> IO (Maybe DrawBufferIndex)
getFragDataLocation (Program program) varName = do
r <- withGLstring varName $ glGetFragDataLocation program
if r < 0
then return Nothing
else return . Just $ fromIntegral r