    -----------------------------------------------------------------------------
    -- |
    -- Module      :  Graphics.Rendering.OpenGL.GL.TransformFeedback
    -- Copyright   :  (c) Sven Panne 2011-2019, Lars Corbijn 2011-2016
    -- License     :  BSD3
    --
    -- Maintainer  :  Sven Panne <svenpanne@gmail.com>
    -- Stability   :  stable
    -- Portability :  portable
    --
    -----------------------------------------------------------------------------

    module Graphics.Rendering.OpenGL.GL.TransformFeedback (
       -- * starting and ending
       beginTransformFeedback, endTransformFeedback,

       -- * TransformFeedbackBufferMode
       TransformFeedbackBufferMode(..), marshalTransformFeedbackBufferMode,
       unmarshalTransformFeedbackBufferMode,

       -- * Shader related
       transformFeedbackBufferMode,
       transformFeedbackVaryings,
       setTransformFeedbackVaryings,

       -- * limits
       maxTransformFeedbackSeparateAttribs,
       maxTransformFeedbackInterleavedComponents,
       maxTransformFeedbackSeparateComponents
    ) where

    import Data.StateVar
    import Foreign.Marshal.Array
    import Graphics.Rendering.OpenGL.GL.ByteString
    import Graphics.Rendering.OpenGL.GL.DataType
    import Graphics.Rendering.OpenGL.GL.PrimitiveMode
    import Graphics.Rendering.OpenGL.GL.PrimitiveModeInternal
    import Graphics.Rendering.OpenGL.GL.QueryUtils
    import Graphics.Rendering.OpenGL.GL.Shaders.Program
    import Graphics.Rendering.OpenGL.GL.Shaders.Variables
    import Graphics.GL

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

    beginTransformFeedback :: PrimitiveMode -> IO ()
    beginTransformFeedback :: PrimitiveMode -> IO ()
    beginTransformFeedback = GLuint -> IO ()
    forall (m :: * -> *). MonadIO m => GLuint -> m ()
    glBeginTransformFeedback (GLuint -> IO ())
    -> (PrimitiveMode -> GLuint) -> PrimitiveMode -> IO ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . PrimitiveMode -> GLuint
    marshalPrimitiveMode

    endTransformFeedback :: IO ()
    endTransformFeedback :: IO ()
    endTransformFeedback = IO ()
    forall (m :: * -> *). MonadIO m => m ()
    glEndTransformFeedback

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

    data TransformFeedbackBufferMode =
         InterleavedAttribs
       | SeparateAttribs
       | SeperateAttribs
       deriving ( TransformFeedbackBufferMode -> TransformFeedbackBufferMode -> Bool
    (TransformFeedbackBufferMode
     -> TransformFeedbackBufferMode -> Bool)
    -> (TransformFeedbackBufferMode
        -> TransformFeedbackBufferMode -> Bool)
    -> Eq TransformFeedbackBufferMode
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: TransformFeedbackBufferMode -> TransformFeedbackBufferMode -> Bool
    == :: TransformFeedbackBufferMode -> TransformFeedbackBufferMode -> Bool
    $c/= :: TransformFeedbackBufferMode -> TransformFeedbackBufferMode -> Bool
    /= :: TransformFeedbackBufferMode -> TransformFeedbackBufferMode -> Bool
    Eq, Eq TransformFeedbackBufferMode
    Eq TransformFeedbackBufferMode =>
    (TransformFeedbackBufferMode
     -> TransformFeedbackBufferMode -> Ordering)
    -> (TransformFeedbackBufferMode
        -> TransformFeedbackBufferMode -> Bool)
    -> (TransformFeedbackBufferMode
        -> TransformFeedbackBufferMode -> Bool)
    -> (TransformFeedbackBufferMode
        -> TransformFeedbackBufferMode -> Bool)
    -> (TransformFeedbackBufferMode
        -> TransformFeedbackBufferMode -> Bool)
    -> (TransformFeedbackBufferMode
        -> TransformFeedbackBufferMode -> TransformFeedbackBufferMode)
    -> (TransformFeedbackBufferMode
        -> TransformFeedbackBufferMode -> TransformFeedbackBufferMode)
    -> Ord TransformFeedbackBufferMode
    TransformFeedbackBufferMode -> TransformFeedbackBufferMode -> Bool
    TransformFeedbackBufferMode
    -> TransformFeedbackBufferMode -> Ordering
    TransformFeedbackBufferMode
    -> TransformFeedbackBufferMode -> TransformFeedbackBufferMode
    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 :: TransformFeedbackBufferMode
    -> TransformFeedbackBufferMode -> Ordering
    compare :: TransformFeedbackBufferMode
    -> TransformFeedbackBufferMode -> Ordering
    $c< :: TransformFeedbackBufferMode -> TransformFeedbackBufferMode -> Bool
    < :: TransformFeedbackBufferMode -> TransformFeedbackBufferMode -> Bool
    $c<= :: TransformFeedbackBufferMode -> TransformFeedbackBufferMode -> Bool
    <= :: TransformFeedbackBufferMode -> TransformFeedbackBufferMode -> Bool
    $c> :: TransformFeedbackBufferMode -> TransformFeedbackBufferMode -> Bool
    > :: TransformFeedbackBufferMode -> TransformFeedbackBufferMode -> Bool
    $c>= :: TransformFeedbackBufferMode -> TransformFeedbackBufferMode -> Bool
    >= :: TransformFeedbackBufferMode -> TransformFeedbackBufferMode -> Bool
    $cmax :: TransformFeedbackBufferMode
    -> TransformFeedbackBufferMode -> TransformFeedbackBufferMode
    max :: TransformFeedbackBufferMode
    -> TransformFeedbackBufferMode -> TransformFeedbackBufferMode
    $cmin :: TransformFeedbackBufferMode
    -> TransformFeedbackBufferMode -> TransformFeedbackBufferMode
    min :: TransformFeedbackBufferMode
    -> TransformFeedbackBufferMode -> TransformFeedbackBufferMode
    Ord, Int -> TransformFeedbackBufferMode -> ShowS
    [TransformFeedbackBufferMode] -> ShowS
    TransformFeedbackBufferMode -> String
    (Int -> TransformFeedbackBufferMode -> ShowS)
    -> (TransformFeedbackBufferMode -> String)
    -> ([TransformFeedbackBufferMode] -> ShowS)
    -> Show TransformFeedbackBufferMode
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> TransformFeedbackBufferMode -> ShowS
    showsPrec :: Int -> TransformFeedbackBufferMode -> ShowS
    $cshow :: TransformFeedbackBufferMode -> String
    show :: TransformFeedbackBufferMode -> String
    $cshowList :: [TransformFeedbackBufferMode] -> ShowS
    showList :: [TransformFeedbackBufferMode] -> ShowS
    Show )
    {-# DEPRECATED SeperateAttribs "Use 'SeparateAttribs' instead." #-}

    marshalTransformFeedbackBufferMode :: TransformFeedbackBufferMode -> GLenum
    marshalTransformFeedbackBufferMode :: TransformFeedbackBufferMode -> GLuint
    marshalTransformFeedbackBufferMode TransformFeedbackBufferMode
    x = case TransformFeedbackBufferMode
    x of
       TransformFeedbackBufferMode
    InterleavedAttribs -> GLuint
    GL_INTERLEAVED_ATTRIBS
       TransformFeedbackBufferMode
    SeparateAttribs -> GLuint
    GL_SEPARATE_ATTRIBS
       TransformFeedbackBufferMode
    SeperateAttribs -> GLuint
    GL_SEPARATE_ATTRIBS

    unmarshalTransformFeedbackBufferMode :: GLenum -> TransformFeedbackBufferMode
    unmarshalTransformFeedbackBufferMode :: GLuint -> TransformFeedbackBufferMode
    unmarshalTransformFeedbackBufferMode GLuint
    x
       | GLuint
    x GLuint -> GLuint -> Bool
    forall a. Eq a => a -> a -> Bool
    == GLuint
    GL_INTERLEAVED_ATTRIBS = TransformFeedbackBufferMode
    InterleavedAttribs
       | GLuint
    x GLuint -> GLuint -> Bool
    forall a. Eq a => a -> a -> Bool
    == GLuint
    GL_SEPARATE_ATTRIBS = TransformFeedbackBufferMode
    SeparateAttribs
       | Bool
    otherwise = String -> TransformFeedbackBufferMode
    forall a. HasCallStack => String -> a
    error (String -> TransformFeedbackBufferMode)
    -> String -> TransformFeedbackBufferMode
    forall a b. (a -> b) -> a -> b
    $ String
    "unmarshalTransformFeedbackBufferMode: illegal value " String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ GLuint -> String
    forall a. Show a => a -> String
    show GLuint
    x

    -- limits
    -- | Max number of seprate atributes or varyings than can be captured
    -- in transformfeedback, initial value 4
    maxTransformFeedbackSeparateAttribs :: GettableStateVar GLint
    maxTransformFeedbackSeparateAttribs :: GettableStateVar GLint
    maxTransformFeedbackSeparateAttribs = GettableStateVar GLint -> GettableStateVar GLint
    forall a. IO a -> IO a
    makeGettableStateVar (GettableStateVar GLint -> GettableStateVar GLint)
    -> GettableStateVar GLint -> GettableStateVar GLint
    forall a b. (a -> b) -> a -> b
    $
       (GLint -> GLint) -> PName1I -> GettableStateVar GLint
    forall p a. GetPName1I p => (GLint -> a) -> p -> IO a
    forall a. (GLint -> a) -> PName1I -> IO a
    getInteger1 GLint -> GLint
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral PName1I
    GetMaxTransformFeedbackSeparateAttribs

    -- | Max number of components to write to a single buffer in
    -- interleaved mod, initial value 64
    maxTransformFeedbackInterleavedComponents :: GettableStateVar GLint
    maxTransformFeedbackInterleavedComponents :: GettableStateVar GLint
    maxTransformFeedbackInterleavedComponents = GettableStateVar GLint -> GettableStateVar GLint
    forall a. IO a -> IO a
    makeGettableStateVar (GettableStateVar GLint -> GettableStateVar GLint)
    -> GettableStateVar GLint -> GettableStateVar GLint
    forall a b. (a -> b) -> a -> b
    $
       (GLint -> GLint) -> PName1I -> GettableStateVar GLint
    forall p a. GetPName1I p => (GLint -> a) -> p -> IO a
    forall a. (GLint -> a) -> PName1I -> IO a
    getInteger1 GLint -> GLint
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral PName1I
    GetMaxTransformFeedbackInterleavedComponents

    -- | Max number of components per attribute or varying in seperate mode
    -- initial value 4
    maxTransformFeedbackSeparateComponents :: GettableStateVar GLint
    maxTransformFeedbackSeparateComponents :: GettableStateVar GLint
    maxTransformFeedbackSeparateComponents = GettableStateVar GLint -> GettableStateVar GLint
    forall a. IO a -> IO a
    makeGettableStateVar (GettableStateVar GLint -> GettableStateVar GLint)
    -> GettableStateVar GLint -> GettableStateVar GLint
    forall a b. (a -> b) -> a -> b
    $
       (GLint -> GLint) -> PName1I -> GettableStateVar GLint
    forall p a. GetPName1I p => (GLint -> a) -> p -> IO a
    forall a. (GLint -> a) -> PName1I -> IO a
    getInteger1 GLint -> GLint
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral PName1I
    GetMaxTransformFeedbackSeparateComponents

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

    -- | Set all the transform feedbacks varyings for this program
    -- it overwrites any previous call to this function
    setTransformFeedbackVaryings :: Program -> [String]
       -> TransformFeedbackBufferMode -> IO ()
    setTransformFeedbackVaryings :: Program -> [String] -> TransformFeedbackBufferMode -> IO ()
    setTransformFeedbackVaryings (Program GLuint
    program) [String]
    sts TransformFeedbackBufferMode
    tfbm = do
       ptSts <- (String -> IO (Ptr GLchar)) -> [String] -> IO [Ptr GLchar]
    forall (t :: * -> *) (m :: * -> *) a b.
    (Traversable t, Monad m) =>
    (a -> m b) -> t a -> m (t b)
    forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
    mapM (\String
    x -> String -> (Ptr GLchar -> IO (Ptr GLchar)) -> IO (Ptr GLchar)
    forall a. String -> (Ptr GLchar -> IO a) -> IO a
    withGLstring String
    x Ptr GLchar -> IO (Ptr GLchar)
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return) [String]
    sts
       stsPtrs <- newArray ptSts
       glTransformFeedbackVaryings program (fromIntegral . length $ sts)  stsPtrs
          (marshalTransformFeedbackBufferMode tfbm)

    -- | Get the currently used transformFeedbackBufferMode
    transformFeedbackBufferMode
       :: Program -> GettableStateVar TransformFeedbackBufferMode
    transformFeedbackBufferMode :: Program -> GettableStateVar TransformFeedbackBufferMode
    transformFeedbackBufferMode = (GLint -> TransformFeedbackBufferMode)
    -> GetProgramPName
    -> Program
    -> GettableStateVar TransformFeedbackBufferMode
    forall a.
    (GLint -> a) -> GetProgramPName -> Program -> GettableStateVar a
    programVar1
       (GLuint -> TransformFeedbackBufferMode
    unmarshalTransformFeedbackBufferMode (GLuint -> TransformFeedbackBufferMode)
    -> (GLint -> GLuint) -> GLint -> TransformFeedbackBufferMode
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . GLint -> GLuint
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral)
       GetProgramPName
    TransformFeedbackBufferMode

    -- | The number of varyings that are currently recorded when in
    -- transform feedback mode
    numTransformFeedbackVaryings :: Program -> GettableStateVar GLuint
    numTransformFeedbackVaryings :: Program -> GettableStateVar GLuint
    numTransformFeedbackVaryings =
       (GLint -> GLuint)
    -> GetProgramPName -> Program -> GettableStateVar GLuint
    forall a.
    (GLint -> a) -> GetProgramPName -> Program -> GettableStateVar a
    programVar1 GLint -> GLuint
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral GetProgramPName
    TransformFeedbackVaryings

    -- | The maximum length of a varying's name for transform feedback mode
    transformFeedbackVaryingMaxLength :: Program -> GettableStateVar GLsizei
    transformFeedbackVaryingMaxLength :: Program -> GettableStateVar GLint
    transformFeedbackVaryingMaxLength
       = (GLint -> GLint)
    -> GetProgramPName -> Program -> GettableStateVar GLint
    forall a.
    (GLint -> a) -> GetProgramPName -> Program -> GettableStateVar a
    programVar1 GLint -> GLint
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral GetProgramPName
    TransformFeedbackVaryingMaxLength

    -- | The name, datatype and size of the transform feedback varyings.
    transformFeedbackVaryings :: Program -> GettableStateVar [(GLint, DataType, String)]
    transformFeedbackVaryings :: Program -> GettableStateVar [(GLint, DataType, String)]
    transformFeedbackVaryings =
       (Program -> GettableStateVar GLuint)
    -> (Program -> GettableStateVar GLint)
    -> (GLuint
        -> GLuint
        -> GLint
        -> Ptr GLint
        -> Ptr GLint
        -> Ptr GLuint
        -> Ptr GLchar
        -> IO ())
    -> (GLuint -> DataType)
    -> Program
    -> GettableStateVar [(GLint, DataType, String)]
    forall a.
    (Program -> GettableStateVar GLuint)
    -> (Program -> GettableStateVar GLint)
    -> (GLuint
        -> GLuint
        -> GLint
        -> Ptr GLint
        -> Ptr GLint
        -> Ptr GLuint
        -> Ptr GLchar
        -> IO ())
    -> (GLuint -> a)
    -> Program
    -> GettableStateVar [(GLint, a, String)]
    activeVars
          Program -> GettableStateVar GLuint
    numTransformFeedbackVaryings
          Program -> GettableStateVar GLint
    transformFeedbackVaryingMaxLength
          GLuint
    -> GLuint
    -> GLint
    -> Ptr GLint
    -> Ptr GLint
    -> Ptr GLuint
    -> Ptr GLchar
    -> IO ()
    forall (m :: * -> *).
    MonadIO m =>
    GLuint
    -> GLuint
    -> GLint
    -> Ptr GLint
    -> Ptr GLint
    -> Ptr GLuint
    -> Ptr GLchar
    -> m ()
    glGetTransformFeedbackVarying
          GLuint -> DataType
    unmarshalDataType