    {-# OPTIONS_HADDOCK hide #-}
    --------------------------------------------------------------------------------
    -- |
    -- Module      :  Graphics.Rendering.OpenGL.GL.FramebufferObjects.FramebufferObjectAttachment
    -- Copyright   :  (c) Sven Panne 2013-2019
    -- License     :  BSD3
    --
    -- Maintainer  :  Sven Panne <svenpanne@gmail.com>
    -- Stability   :  stable
    -- Portability :  portable
    --
    -- This is a purely internal module for marshaling FramebufferObjectAttachments.
    --
    --------------------------------------------------------------------------------

    module Graphics.Rendering.OpenGL.GL.FramebufferObjects.FramebufferObjectAttachment (
       FramebufferObjectAttachment(..),
       marshalFramebufferObjectAttachment,
       unmarshalFramebufferObjectAttachment,
       unmarshalFramebufferObjectAttachmentSafe,
       fboaToBufferMode, fboaFromBufferMode,

       FramebufferAttachment(..), getFBAParameteriv
    ) where

    import Data.Maybe
    import Foreign.Marshal
    import Graphics.Rendering.OpenGL.GL.BufferMode
    import Graphics.Rendering.OpenGL.GL.FramebufferObjects.FramebufferTarget
    import Graphics.Rendering.OpenGL.GL.PeekPoke
    import Graphics.GL

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

    data FramebufferObjectAttachment =
         ColorAttachment !GLuint
       | DepthAttachment
       | StencilAttachment
       | DepthStencilAttachment
       deriving ( FramebufferObjectAttachment -> FramebufferObjectAttachment -> Bool
    (FramebufferObjectAttachment
     -> FramebufferObjectAttachment -> Bool)
    -> (FramebufferObjectAttachment
        -> FramebufferObjectAttachment -> Bool)
    -> Eq FramebufferObjectAttachment
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: FramebufferObjectAttachment -> FramebufferObjectAttachment -> Bool
    == :: FramebufferObjectAttachment -> FramebufferObjectAttachment -> Bool
    $c/= :: FramebufferObjectAttachment -> FramebufferObjectAttachment -> Bool
    /= :: FramebufferObjectAttachment -> FramebufferObjectAttachment -> Bool
    Eq, Eq FramebufferObjectAttachment
    Eq FramebufferObjectAttachment =>
    (FramebufferObjectAttachment
     -> FramebufferObjectAttachment -> Ordering)
    -> (FramebufferObjectAttachment
        -> FramebufferObjectAttachment -> Bool)
    -> (FramebufferObjectAttachment
        -> FramebufferObjectAttachment -> Bool)
    -> (FramebufferObjectAttachment
        -> FramebufferObjectAttachment -> Bool)
    -> (FramebufferObjectAttachment
        -> FramebufferObjectAttachment -> Bool)
    -> (FramebufferObjectAttachment
        -> FramebufferObjectAttachment -> FramebufferObjectAttachment)
    -> (FramebufferObjectAttachment
        -> FramebufferObjectAttachment -> FramebufferObjectAttachment)
    -> Ord FramebufferObjectAttachment
    FramebufferObjectAttachment -> FramebufferObjectAttachment -> Bool
    FramebufferObjectAttachment
    -> FramebufferObjectAttachment -> Ordering
    FramebufferObjectAttachment
    -> FramebufferObjectAttachment -> FramebufferObjectAttachment
    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 :: FramebufferObjectAttachment
    -> FramebufferObjectAttachment -> Ordering
    compare :: FramebufferObjectAttachment
    -> FramebufferObjectAttachment -> Ordering
    $c< :: FramebufferObjectAttachment -> FramebufferObjectAttachment -> Bool
    < :: FramebufferObjectAttachment -> FramebufferObjectAttachment -> Bool
    $c<= :: FramebufferObjectAttachment -> FramebufferObjectAttachment -> Bool
    <= :: FramebufferObjectAttachment -> FramebufferObjectAttachment -> Bool
    $c> :: FramebufferObjectAttachment -> FramebufferObjectAttachment -> Bool
    > :: FramebufferObjectAttachment -> FramebufferObjectAttachment -> Bool
    $c>= :: FramebufferObjectAttachment -> FramebufferObjectAttachment -> Bool
    >= :: FramebufferObjectAttachment -> FramebufferObjectAttachment -> Bool
    $cmax :: FramebufferObjectAttachment
    -> FramebufferObjectAttachment -> FramebufferObjectAttachment
    max :: FramebufferObjectAttachment
    -> FramebufferObjectAttachment -> FramebufferObjectAttachment
    $cmin :: FramebufferObjectAttachment
    -> FramebufferObjectAttachment -> FramebufferObjectAttachment
    min :: FramebufferObjectAttachment
    -> FramebufferObjectAttachment -> FramebufferObjectAttachment
    Ord, Int -> FramebufferObjectAttachment -> ShowS
    [FramebufferObjectAttachment] -> ShowS
    FramebufferObjectAttachment -> String
    (Int -> FramebufferObjectAttachment -> ShowS)
    -> (FramebufferObjectAttachment -> String)
    -> ([FramebufferObjectAttachment] -> ShowS)
    -> Show FramebufferObjectAttachment
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> FramebufferObjectAttachment -> ShowS
    showsPrec :: Int -> FramebufferObjectAttachment -> ShowS
    $cshow :: FramebufferObjectAttachment -> String
    show :: FramebufferObjectAttachment -> String
    $cshowList :: [FramebufferObjectAttachment] -> ShowS
    showList :: [FramebufferObjectAttachment] -> ShowS
    Show )

    marshalFramebufferObjectAttachment :: FramebufferObjectAttachment -> Maybe GLenum
    marshalFramebufferObjectAttachment :: FramebufferObjectAttachment -> Maybe GLuint
    marshalFramebufferObjectAttachment FramebufferObjectAttachment
    x = case FramebufferObjectAttachment
    x of
       ColorAttachment GLuint
    c -> let ec :: GLuint
    ec = GLuint -> GLuint
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral GLuint
    c in if GLuint
    ec GLuint -> GLuint -> Bool
    forall a. Ord a => a -> a -> Bool
    >= GLuint
    maxColorAttachments
          then Maybe GLuint
    forall a. Maybe a
    Nothing
          else GLuint -> Maybe GLuint
    forall a. a -> Maybe a
    Just (GLuint -> Maybe GLuint) -> GLuint -> Maybe GLuint
    forall a b. (a -> b) -> a -> b
    $ GLuint
    GL_COLOR_ATTACHMENT0 GLuint -> GLuint -> GLuint
    forall a. Num a => a -> a -> a
    + GLuint
    ec
       FramebufferObjectAttachment
    DepthAttachment -> GLuint -> Maybe GLuint
    forall a. a -> Maybe a
    Just GLuint
    GL_DEPTH_ATTACHMENT
       FramebufferObjectAttachment
    StencilAttachment -> GLuint -> Maybe GLuint
    forall a. a -> Maybe a
    Just GLuint
    GL_STENCIL_ATTACHMENT
       FramebufferObjectAttachment
    DepthStencilAttachment -> GLuint -> Maybe GLuint
    forall a. a -> Maybe a
    Just GLuint
    GL_DEPTH_STENCIL_ATTACHMENT

    unmarshalFramebufferObjectAttachment :: GLenum -> FramebufferObjectAttachment
    unmarshalFramebufferObjectAttachment :: GLuint -> FramebufferObjectAttachment
    unmarshalFramebufferObjectAttachment GLuint
    x = FramebufferObjectAttachment
    -> (FramebufferObjectAttachment -> FramebufferObjectAttachment)
    -> Maybe FramebufferObjectAttachment
    -> FramebufferObjectAttachment
    forall b a. b -> (a -> b) -> Maybe a -> b
    maybe
       (String -> FramebufferObjectAttachment
    forall a. HasCallStack => String -> a
    error (String -> FramebufferObjectAttachment)
    -> String -> FramebufferObjectAttachment
    forall a b. (a -> b) -> a -> b
    $ String
    "unmarshalFramebufferObjectAttachment: unknown enum value " String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ GLuint -> String
    forall a. Show a => a -> String
    show GLuint
    x) FramebufferObjectAttachment -> FramebufferObjectAttachment
    forall a. a -> a
    id (Maybe FramebufferObjectAttachment -> FramebufferObjectAttachment)
    -> Maybe FramebufferObjectAttachment -> FramebufferObjectAttachment
    forall a b. (a -> b) -> a -> b
    $
          GLuint -> Maybe FramebufferObjectAttachment
    unmarshalFramebufferObjectAttachmentSafe GLuint
    x
    --unmarshalFramebufferObjectAttachment x
    --   | x == GL_DEPTH_ATTACHMENT = DepthAttachment
    --   | x == GL_STENCIL_ATTACHMENT = StencilAttachment
    --   | x == GL_DEPTH_STENCIL_ATTACHMENT = DepthStencilAttachment
    --   | x >= gl_COLOR_ATTACHMENT0 && x <= gl_COLOR_ATTACHMENT15
    --      = ColorAttachment . fromIntegral $ x - gl_COLOR_ATTACHMENT0
    --   | otherwise = error $ "unmarshalFramebufferObjectAttachment: unknown enum value " ++ show x

    unmarshalFramebufferObjectAttachmentSafe :: GLenum -> Maybe FramebufferObjectAttachment
    unmarshalFramebufferObjectAttachmentSafe :: GLuint -> Maybe FramebufferObjectAttachment
    unmarshalFramebufferObjectAttachmentSafe GLuint
    x
       | GLuint
    x GLuint -> GLuint -> Bool
    forall a. Eq a => a -> a -> Bool
    == GLuint
    GL_DEPTH_ATTACHMENT = FramebufferObjectAttachment -> Maybe FramebufferObjectAttachment
    forall a. a -> Maybe a
    Just FramebufferObjectAttachment
    DepthAttachment
       | GLuint
    x GLuint -> GLuint -> Bool
    forall a. Eq a => a -> a -> Bool
    == GLuint
    GL_STENCIL_ATTACHMENT = FramebufferObjectAttachment -> Maybe FramebufferObjectAttachment
    forall a. a -> Maybe a
    Just FramebufferObjectAttachment
    StencilAttachment
       | GLuint
    x GLuint -> GLuint -> Bool
    forall a. Eq a => a -> a -> Bool
    == GLuint
    GL_DEPTH_STENCIL_ATTACHMENT = FramebufferObjectAttachment -> Maybe FramebufferObjectAttachment
    forall a. a -> Maybe a
    Just FramebufferObjectAttachment
    DepthStencilAttachment
       | GLuint
    x GLuint -> GLuint -> Bool
    forall a. Ord a => a -> a -> Bool
    >= GLuint
    GL_COLOR_ATTACHMENT0 Bool -> Bool -> Bool
    && GLuint
    x GLuint -> GLuint -> Bool
    forall a. Ord a => a -> a -> Bool
    <= GLuint
    GL_COLOR_ATTACHMENT0 GLuint -> GLuint -> GLuint
    forall a. Num a => a -> a -> a
    + GLuint
    maxColorAttachments
          = FramebufferObjectAttachment -> Maybe FramebufferObjectAttachment
    forall a. a -> Maybe a
    Just (FramebufferObjectAttachment -> Maybe FramebufferObjectAttachment)
    -> (GLuint -> FramebufferObjectAttachment)
    -> GLuint
    -> Maybe FramebufferObjectAttachment
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . GLuint -> FramebufferObjectAttachment
    ColorAttachment (GLuint -> FramebufferObjectAttachment)
    -> (GLuint -> GLuint) -> GLuint -> FramebufferObjectAttachment
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . GLuint -> GLuint
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral (GLuint -> Maybe FramebufferObjectAttachment)
    -> GLuint -> Maybe FramebufferObjectAttachment
    forall a b. (a -> b) -> a -> b
    $ GLuint
    x GLuint -> GLuint -> GLuint
    forall a. Num a => a -> a -> a
    - GLuint
    GL_COLOR_ATTACHMENT0
       | Bool
    otherwise = Maybe FramebufferObjectAttachment
    forall a. Maybe a
    Nothing

    fboaToBufferMode :: FramebufferObjectAttachment -> Maybe BufferMode
    fboaToBufferMode :: FramebufferObjectAttachment -> Maybe BufferMode
    fboaToBufferMode (ColorAttachment GLuint
    i) = BufferMode -> Maybe BufferMode
    forall a. a -> Maybe a
    Just (BufferMode -> Maybe BufferMode)
    -> (GLsizei -> BufferMode) -> GLsizei -> Maybe BufferMode
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . GLsizei -> BufferMode
    FBOColorAttachment (GLsizei -> Maybe BufferMode) -> GLsizei -> Maybe BufferMode
    forall a b. (a -> b) -> a -> b
    $ GLuint -> GLsizei
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral GLuint
    i
    fboaToBufferMode FramebufferObjectAttachment
    _                   = Maybe BufferMode
    forall a. Maybe a
    Nothing

    fboaFromBufferMode :: BufferMode -> Maybe FramebufferObjectAttachment
    fboaFromBufferMode :: BufferMode -> Maybe FramebufferObjectAttachment
    fboaFromBufferMode (FBOColorAttachment GLsizei
    i) = FramebufferObjectAttachment -> Maybe FramebufferObjectAttachment
    forall a. a -> Maybe a
    Just (FramebufferObjectAttachment -> Maybe FramebufferObjectAttachment)
    -> (GLuint -> FramebufferObjectAttachment)
    -> GLuint
    -> Maybe FramebufferObjectAttachment
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . GLuint -> FramebufferObjectAttachment
    ColorAttachment (GLuint -> Maybe FramebufferObjectAttachment)
    -> GLuint -> Maybe FramebufferObjectAttachment
    forall a b. (a -> b) -> a -> b
    $ GLsizei -> GLuint
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral GLsizei
    i
    fboaFromBufferMode BufferMode
    _                      = Maybe FramebufferObjectAttachment
    forall a. Maybe a
    Nothing

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

    class Show a => FramebufferAttachment a where
       marshalAttachment :: a -> Maybe GLenum
       unmarshalAttachment :: GLenum -> a
       unmarshalAttachmentSafe :: GLenum -> Maybe a

    instance FramebufferAttachment FramebufferObjectAttachment where
       marshalAttachment :: FramebufferObjectAttachment -> Maybe GLuint
    marshalAttachment = FramebufferObjectAttachment -> Maybe GLuint
    marshalFramebufferObjectAttachment
       unmarshalAttachment :: GLuint -> FramebufferObjectAttachment
    unmarshalAttachment = GLuint -> FramebufferObjectAttachment
    unmarshalFramebufferObjectAttachment
       unmarshalAttachmentSafe :: GLuint -> Maybe FramebufferObjectAttachment
    unmarshalAttachmentSafe = GLuint -> Maybe FramebufferObjectAttachment
    unmarshalFramebufferObjectAttachmentSafe

    instance FramebufferAttachment BufferMode where
       marshalAttachment :: BufferMode -> Maybe GLuint
    marshalAttachment = BufferMode -> Maybe GLuint
    marshalBufferMode
       unmarshalAttachment :: GLuint -> BufferMode
    unmarshalAttachment = GLuint -> BufferMode
    unmarshalBufferMode
       unmarshalAttachmentSafe :: GLuint -> Maybe BufferMode
    unmarshalAttachmentSafe = GLuint -> Maybe BufferMode
    unmarshalBufferModeSafe

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

    getFBAParameteriv :: FramebufferAttachment fba => FramebufferTarget -> fba
        -> (GLint -> a) -> GLenum -> IO a
    getFBAParameteriv :: forall fba a.
    FramebufferAttachment fba =>
    FramebufferTarget -> fba -> (GLsizei -> a) -> GLuint -> IO a
    getFBAParameteriv FramebufferTarget
    fbt fba
    fba GLsizei -> a
    f GLuint
    p = GLsizei -> (Ptr GLsizei -> IO a) -> IO a
    forall a b. Storable a => a -> (Ptr a -> IO b) -> IO b
    with GLsizei
    0 ((Ptr GLsizei -> IO a) -> IO a) -> (Ptr GLsizei -> IO a) -> IO a
    forall a b. (a -> b) -> a -> b
    $ \Ptr GLsizei
    buf -> do
       GLuint -> GLuint -> GLuint -> Ptr GLsizei -> IO ()
    forall (m :: * -> *).
    MonadIO m =>
    GLuint -> GLuint -> GLuint -> Ptr GLsizei -> m ()
    glGetFramebufferAttachmentParameteriv (FramebufferTarget -> GLuint
    marshalFramebufferTarget FramebufferTarget
    fbt)
          GLuint
    mfba GLuint
    p Ptr GLsizei
    buf
       (GLsizei -> a) -> Ptr GLsizei -> IO a
    forall a b. Storable a => (a -> b) -> Ptr a -> IO b
    peek1 GLsizei -> a
    f Ptr GLsizei
    buf
          where mfba :: GLuint
    mfba = GLuint -> Maybe GLuint -> GLuint
    forall a. a -> Maybe a -> a
    fromMaybe (String -> GLuint
    forall a. HasCallStack => String -> a
    error (String -> GLuint) -> String -> GLuint
    forall a b. (a -> b) -> a -> b
    $ String
    "invalid value" String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ fba -> String
    forall a. Show a => a -> String
    show fba
    fba) (fba -> Maybe GLuint
    forall a. FramebufferAttachment a => a -> Maybe GLuint
    marshalAttachment fba
    fba)