-----------------------------------------------------------------------------
-- |
-- 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
   [Ptr GLchar]
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
   Ptr (Ptr GLchar)
stsPtrs <- [Ptr GLchar] -> IO (Ptr (Ptr GLchar))
forall a. Storable a => [a] -> IO (Ptr a)
newArray [Ptr GLchar]
ptSts
   GLuint -> GLint -> Ptr (Ptr GLchar) -> GLuint -> IO ()
forall (m :: * -> *).
MonadIO m =>
GLuint -> GLint -> Ptr (Ptr GLchar) -> GLuint -> m ()
glTransformFeedbackVaryings GLuint
program (Int -> GLint
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> GLint) -> ([String] -> Int) -> [String] -> GLint
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [String] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length ([String] -> GLint) -> [String] -> GLint
forall a b. (a -> b) -> a -> b
$ [String]
sts)  Ptr (Ptr GLchar)
stsPtrs
      (TransformFeedbackBufferMode -> GLuint
marshalTransformFeedbackBufferMode TransformFeedbackBufferMode
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