    {-# OPTIONS_HADDOCK hide #-}
    --------------------------------------------------------------------------------
    -- |
    -- Module      :  Graphics.Rendering.OpenGL.GL.Shaders.Program
    -- Copyright   :  (c) Sven Panne 2019
    -- License     :  BSD3
    --
    -- Maintainer  :  Sven Panne <svenpanne@gmail.com>
    -- Stability   :  stable
    -- Portability :  portable
    --
    -- This is a purely internal module for handling program objects and related
    -- queries.
    --
    --------------------------------------------------------------------------------

    module Graphics.Rendering.OpenGL.GL.Shaders.Program (
       Program(..),
       GetProgramPName(..), marshalGetProgramPName,
       programVar1, programVar3
    ) where

    import Control.Monad.IO.Class
    import Data.ObjectName
    import Data.StateVar
    import Foreign.Marshal.Utils ( with )
    import Foreign.Ptr ( Ptr )
    import Graphics.Rendering.OpenGL.GL.DebugOutput
    import Graphics.Rendering.OpenGL.GL.GLboolean
    import Graphics.Rendering.OpenGL.GL.PeekPoke
    import Graphics.Rendering.OpenGL.GL.QueryUtils
    import Graphics.GL

    --------------------------------------------------------------------------------

    newtype Program = Program { Program -> GLuint
    programID :: GLuint }
       deriving ( Program -> Program -> Bool
    (Program -> Program -> Bool)
    -> (Program -> Program -> Bool) -> Eq Program
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: Program -> Program -> Bool
    == :: Program -> Program -> Bool
    $c/= :: Program -> Program -> Bool
    /= :: Program -> Program -> Bool
    Eq, Eq Program
    Eq Program =>
    (Program -> Program -> Ordering)
    -> (Program -> Program -> Bool)
    -> (Program -> Program -> Bool)
    -> (Program -> Program -> Bool)
    -> (Program -> Program -> Bool)
    -> (Program -> Program -> Program)
    -> (Program -> Program -> Program)
    -> Ord Program
    Program -> Program -> Bool
    Program -> Program -> Ordering
    Program -> Program -> Program
    forall a.
    Eq a =>
    (a -> a -> Ordering)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> a)
    -> (a -> a -> a)
    -> Ord a
    $ccompare :: Program -> Program -> Ordering
    compare :: Program -> Program -> Ordering
    $c< :: Program -> Program -> Bool
    < :: Program -> Program -> Bool
    $c<= :: Program -> Program -> Bool
    <= :: Program -> Program -> Bool
    $c> :: Program -> Program -> Bool
    > :: Program -> Program -> Bool
    $c>= :: Program -> Program -> Bool
    >= :: Program -> Program -> Bool
    $cmax :: Program -> Program -> Program
    max :: Program -> Program -> Program
    $cmin :: Program -> Program -> Program
    min :: Program -> Program -> Program
    Ord, Int -> Program -> ShowS
    [Program] -> ShowS
    Program -> String
    (Int -> Program -> ShowS)
    -> (Program -> String) -> ([Program] -> ShowS) -> Show Program
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> Program -> ShowS
    showsPrec :: Int -> Program -> ShowS
    $cshow :: Program -> String
    show :: Program -> String
    $cshowList :: [Program] -> ShowS
    showList :: [Program] -> ShowS
    Show )

    instance ObjectName Program where
       isObjectName :: forall (m :: * -> *). MonadIO m => Program -> m Bool
    isObjectName = IO Bool -> m Bool
    forall a. IO a -> m a
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO Bool -> m Bool) -> (Program -> IO Bool) -> Program -> m Bool
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (GLboolean -> Bool) -> IO GLboolean -> IO Bool
    forall a b. (a -> b) -> IO a -> IO b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap GLboolean -> Bool
    forall a. (Eq a, Num a) => a -> Bool
    unmarshalGLboolean (IO GLboolean -> IO Bool)
    -> (Program -> IO GLboolean) -> Program -> IO Bool
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . GLuint -> IO GLboolean
    forall (m :: * -> *). MonadIO m => GLuint -> m GLboolean
    glIsProgram (GLuint -> IO GLboolean)
    -> (Program -> GLuint) -> Program -> IO GLboolean
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Program -> GLuint
    programID
       deleteObjectName :: forall (m :: * -> *). MonadIO m => Program -> m ()
    deleteObjectName = IO () -> m ()
    forall a. IO a -> m a
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO () -> m ()) -> (Program -> IO ()) -> Program -> m ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . GLuint -> IO ()
    forall (m :: * -> *). MonadIO m => GLuint -> m ()
    glDeleteProgram (GLuint -> IO ()) -> (Program -> GLuint) -> Program -> IO ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Program -> GLuint
    programID

    instance CanBeLabeled Program where
       objectLabel :: Program -> StateVar (Maybe String)
    objectLabel = GLuint -> GLuint -> StateVar (Maybe String)
    objectNameLabel GLuint
    GL_PROGRAM (GLuint -> StateVar (Maybe String))
    -> (Program -> GLuint) -> Program -> StateVar (Maybe String)
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Program -> GLuint
    programID

    --------------------------------------------------------------------------------

    data GetProgramPName =
         ProgramDeleteStatus
       | LinkStatus
       | ValidateStatus
       | ProgramInfoLogLength
       | AttachedShaders
       | ActiveAttributes
       | ActiveAttributeMaxLength
       | ActiveUniforms
       | ActiveUniformMaxLength
       | TransformFeedbackBufferMode
       | TransformFeedbackVaryings
       | TransformFeedbackVaryingMaxLength
       | ActiveUniformBlocks
       | ActiveUniformBlockMaxNameLength
       | GeometryVerticesOut
       | GeometryInputType
       | GeometryOutputType
       | GeometryShaderInvocations
       | TessControlOutputVertices
       | TessGenMode
       | TessGenSpacing
       | TessGenVertexOrder
       | TessGenPointMode
       | ComputeWorkGroupSize  -- 3 integers!
       | ProgramSeparable
       | ProgramBinaryRetrievableHint
       | ActiveAtomicCounterBuffers
       | ProgramBinaryLength

    marshalGetProgramPName :: GetProgramPName -> GLenum
    marshalGetProgramPName :: GetProgramPName -> GLuint
    marshalGetProgramPName GetProgramPName
    x = case GetProgramPName
    x of
       GetProgramPName
    ProgramDeleteStatus -> GLuint
    GL_DELETE_STATUS
       GetProgramPName
    LinkStatus -> GLuint
    GL_LINK_STATUS
       GetProgramPName
    ValidateStatus -> GLuint
    GL_VALIDATE_STATUS
       GetProgramPName
    ProgramInfoLogLength -> GLuint
    GL_INFO_LOG_LENGTH
       GetProgramPName
    AttachedShaders -> GLuint
    GL_ATTACHED_SHADERS
       GetProgramPName
    ActiveAttributes -> GLuint
    GL_ACTIVE_ATTRIBUTES
       GetProgramPName
    ActiveAttributeMaxLength -> GLuint
    GL_ACTIVE_ATTRIBUTE_MAX_LENGTH
       GetProgramPName
    ActiveUniforms -> GLuint
    GL_ACTIVE_UNIFORMS
       GetProgramPName
    ActiveUniformMaxLength -> GLuint
    GL_ACTIVE_UNIFORM_MAX_LENGTH
       GetProgramPName
    TransformFeedbackBufferMode -> GLuint
    GL_TRANSFORM_FEEDBACK_BUFFER_MODE
       GetProgramPName
    TransformFeedbackVaryings -> GLuint
    GL_TRANSFORM_FEEDBACK_VARYINGS
       GetProgramPName
    TransformFeedbackVaryingMaxLength -> GLuint
    GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH
       GetProgramPName
    ActiveUniformBlocks -> GLuint
    GL_ACTIVE_UNIFORM_BLOCKS
       GetProgramPName
    ActiveUniformBlockMaxNameLength -> GLuint
    GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH
       GetProgramPName
    GeometryVerticesOut -> GLuint
    GL_GEOMETRY_VERTICES_OUT
       GetProgramPName
    GeometryInputType -> GLuint
    GL_GEOMETRY_INPUT_TYPE
       GetProgramPName
    GeometryOutputType -> GLuint
    GL_GEOMETRY_OUTPUT_TYPE
       GetProgramPName
    GeometryShaderInvocations -> GLuint
    GL_GEOMETRY_SHADER_INVOCATIONS
       GetProgramPName
    TessControlOutputVertices -> GLuint
    GL_TESS_CONTROL_OUTPUT_VERTICES
       GetProgramPName
    TessGenMode -> GLuint
    GL_TESS_GEN_MODE
       GetProgramPName
    TessGenSpacing -> GLuint
    GL_TESS_GEN_SPACING
       GetProgramPName
    TessGenVertexOrder -> GLuint
    GL_TESS_GEN_VERTEX_ORDER
       GetProgramPName
    TessGenPointMode -> GLuint
    GL_TESS_GEN_POINT_MODE
       GetProgramPName
    ComputeWorkGroupSize -> GLuint
    GL_COMPUTE_WORK_GROUP_SIZE
       GetProgramPName
    ProgramSeparable -> GLuint
    GL_PROGRAM_SEPARABLE
       GetProgramPName
    ProgramBinaryRetrievableHint -> GLuint
    GL_PROGRAM_BINARY_RETRIEVABLE_HINT
       GetProgramPName
    ActiveAtomicCounterBuffers -> GLuint
    GL_ACTIVE_ATOMIC_COUNTER_BUFFERS
       GetProgramPName
    ProgramBinaryLength -> GLuint
    GL_PROGRAM_BINARY_LENGTH

    programVar1 :: (GLint -> a) -> GetProgramPName -> Program -> GettableStateVar a
    programVar1 :: forall a.
    (GLint -> a) -> GetProgramPName -> Program -> GettableStateVar a
    programVar1 = (Ptr GLint -> IO a) -> GetProgramPName -> Program -> IO a
    forall a. (Ptr GLint -> IO a) -> GetProgramPName -> Program -> IO a
    programVarN ((Ptr GLint -> IO a) -> GetProgramPName -> Program -> IO a)
    -> ((GLint -> a) -> Ptr GLint -> IO a)
    -> (GLint -> a)
    -> GetProgramPName
    -> Program
    -> IO a
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (GLint -> a) -> Ptr GLint -> IO a
    forall a b. Storable a => (a -> b) -> Ptr a -> IO b
    peek1

    programVar3 :: (GLint -> GLint -> GLint -> a) -> GetProgramPName -> Program -> GettableStateVar a
    programVar3 :: forall a.
    (GLint -> GLint -> GLint -> a)
    -> GetProgramPName -> Program -> GettableStateVar a
    programVar3 = (Ptr GLint -> IO a) -> GetProgramPName -> Program -> IO a
    forall a. (Ptr GLint -> IO a) -> GetProgramPName -> Program -> IO a
    programVarN ((Ptr GLint -> IO a) -> GetProgramPName -> Program -> IO a)
    -> ((GLint -> GLint -> GLint -> a) -> Ptr GLint -> IO a)
    -> (GLint -> GLint -> GLint -> a)
    -> GetProgramPName
    -> Program
    -> IO a
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (GLint -> GLint -> GLint -> a) -> Ptr GLint -> IO a
    forall a b. Storable a => (a -> a -> a -> b) -> Ptr a -> IO b
    peek3

    programVarN :: (Ptr GLint -> IO a) -> GetProgramPName -> Program -> GettableStateVar a
    programVarN :: forall a. (Ptr GLint -> IO a) -> GetProgramPName -> Program -> IO a
    programVarN Ptr GLint -> IO a
    f GetProgramPName
    p Program
    program =
       IO a -> IO a
    forall a. IO a -> IO a
    makeGettableStateVar (IO a -> IO a) -> IO a -> IO a
    forall a b. (a -> b) -> a -> b
    $
          GLint -> (Ptr GLint -> IO a) -> IO a
    forall a b. Storable a => a -> (Ptr a -> IO b) -> IO b
    with GLint
    0 ((Ptr GLint -> IO a) -> IO a) -> (Ptr GLint -> IO a) -> IO a
    forall a b. (a -> b) -> a -> b
    $ \Ptr GLint
    buf -> do
             GLuint -> GLuint -> Ptr GLint -> IO ()
    forall (m :: * -> *).
    MonadIO m =>
    GLuint -> GLuint -> Ptr GLint -> m ()
    glGetProgramiv (Program -> GLuint
    programID Program
    program) (GetProgramPName -> GLuint
    marshalGetProgramPName GetProgramPName
    p) Ptr GLint
    buf
             Ptr GLint -> IO a
    f Ptr GLint
    buf