{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TupleSections #-}
module Graphics.GPipe.Internal.FrameBuffer where
import Control.Applicative
import Control.Monad (when, void)
import Control.Monad.Trans.Class
import Control.Monad.Trans.State.Lazy
import qualified Control.Monad.Trans.State.Strict as StrictState
import Control.Monad.Trans.Writer.Lazy
import Data.List (intercalate)
import Graphics.GPipe.Internal.Compiler
import Graphics.GPipe.Internal.Context
import Graphics.GPipe.Internal.Expr
import Graphics.GPipe.Internal.Format
import Graphics.GPipe.Internal.FragmentStream
import Graphics.GPipe.Internal.PrimitiveStream
import Graphics.GPipe.Internal.Shader
import Graphics.GPipe.Internal.Texture
import Data.Word (Word)
import Foreign.Marshal.Utils
import Graphics.GL.Core33
import Graphics.GL.Types
import Data.IORef
import Foreign.Marshal.Alloc
import Foreign.Storable (peek)
import Foreign.Marshal.Array (withArray)
import Foreign.Ptr (nullPtr)
import Linear.V4
import Control.Monad.IO.Class
import Control.Monad.Trans.Except
import qualified Data.IntMap as IMap
newtype DrawColors os s a = DrawColors (StateT Int (Writer [Int -> (ExprM (), GlobDeclM (), s -> (IO FBOKey, IO (), IO ()))]) a) deriving (Functor, Applicative, Monad)
runDrawColors :: DrawColors os s a -> (ExprM (), GlobDeclM (), s -> (IO [FBOKey], IO (), IO ()))
runDrawColors (DrawColors m) = foldl sf (return (), return (), const (return [], return (), return ())) $ zip [0..] $ execWriter (runStateT m 0)
where sf (ms, mg, mio) (n, f) = let (sh, g, io) = f n in (ms >> sh, mg >> g, sf' mio io )
sf' mio io s = let (a,b,c) = mio s
(x,y,z) = io s
in (do ns <- a
n <- x
return $ ns ++ [n]
, b >> y, c >> z)
drawColor :: forall c s os. ColorRenderable c => (s -> (Image (Format c), ColorMask c, UseBlending)) -> FragColor c -> DrawColors os s ()
drawColor sf c = DrawColors $ do n <- get
put $ n+1
lift $ tell [\ix -> make3 (setColor cf ix c) $ \s -> let (i, mask, o) = sf s
n' = fromIntegral n
useblend = if o then glEnablei GL_BLEND n' else glDisablei GL_BLEND n'
in (getImageFBOKey i,
getImageBinding i (GL_COLOR_ATTACHMENT0 + n'),
do
useblend
setGlColorMask cf n' mask)
]
where cf = undefined :: c
draw :: forall a os f s. (s -> Blending) -> FragmentStream a -> (a -> DrawColors os s ()) -> Shader os s ()
drawDepth :: forall a os f s d. DepthRenderable d => (s -> (Blending, Image (Format d), DepthOption)) -> FragmentStream (a, FragDepth) -> (a -> DrawColors os s ()) -> Shader os s ()
drawStencil :: forall a os f s st. StencilRenderable st => (s -> (Blending, Image (Format st), StencilOptions)) -> FragmentStream a -> (a -> DrawColors os s ()) -> Shader os s ()
drawDepthStencil :: forall a os f s d st. (DepthRenderable d, StencilRenderable st) => (s -> (Blending, Image (Format d), Image (Format st), DepthStencilOption)) -> FragmentStream (a, FragDepth) -> (a -> DrawColors os s ()) -> Shader os s ()
makeFBOKeys :: IO [FBOKey] -> IO (Maybe FBOKey) -> IO (Maybe FBOKey) -> IO FBOKeys
makeFBOKeys c d s = do c' <- c
d' <- d
s' <- s
return $ FBOKeys c' d' s'
draw sf fs m = Shader $ tellDrawcalls fs $ \c -> let (sh,g,ioc) = runDrawColors (m c) in (sh, g, f ioc)
where f ioc s = let (fbokeyio, fboio, io) = ioc s
b = sf s
in (Right (makeFBOKeys fbokeyio (return Nothing) (return Nothing), fboio)
, io >> glDisable GL_DEPTH_TEST >> glDisable GL_STENCIL_TEST >> setGlBlend b)
drawDepth sf fs m = Shader $ tellDrawcalls fs $ \(c,d) -> let (sh,g,ioc) = runDrawColors (m c) in (sh >> setDepth d, g, f ioc)
where f ioc s = let (fbokeyio, fboio, io) = ioc s
(b, di, o) = sf s
in (Right (makeFBOKeys fbokeyio (Just <$> getImageFBOKey di) (return Nothing)
, fboio >> getImageBinding di GL_DEPTH_ATTACHMENT)
, io >> glDisable GL_STENCIL_TEST >> setGlBlend b >> setGlDepthOptions o)
drawStencil sf fs m = Shader $ tellDrawcalls fs $ \c -> let (sh,g,ioc) = runDrawColors (m c) in (sh, g, f ioc )
where f ioc s = let (fbokeyio, fboio, io) = ioc s
(b, si, o) = sf s
in (Right (makeFBOKeys fbokeyio (return Nothing) (Just <$> getImageFBOKey si)
, fboio >> getImageBinding si GL_STENCIL_ATTACHMENT)
, io >> glDisable GL_DEPTH_TEST >> setGlBlend b >> setGlStencilOptions o OpZero OpZero)
drawDepthStencil sf fs m = Shader $ tellDrawcalls fs $ \(c,d) -> let (sh,g,ioc) = runDrawColors (m c) in (sh >> setDepth d, g, f ioc )
where f ioc s = let (fbokeyio, fboio, io) = ioc s
(b, di, si, o) = sf s
in (Right (makeFBOKeys fbokeyio (Just <$> getImageFBOKey di) (Just <$> getImageFBOKey si)
, fboio >> getCombinedBinding di si)
, io >> setGlBlend b >> setGlDepthStencilOptions o)
getCombinedBinding di si | imageEquals di si = getImageBinding di GL_DEPTH_STENCIL_ATTACHMENT
| otherwise = getImageBinding di GL_DEPTH_ATTACHMENT >> getImageBinding si GL_STENCIL_ATTACHMENT
drawWindowColor :: forall os s c ds. ContextColorFormat c => (s -> (Window os c ds, ContextColorOption c)) -> FragmentStream (FragColor c) -> Shader os s ()
drawWindowDepth :: forall os s c ds. DepthRenderable ds => (s -> (Window os c ds, DepthOption)) -> FragmentStream FragDepth -> Shader os s ()
drawWindowColorDepth :: forall os s c ds. (ContextColorFormat c, DepthRenderable ds) => (s -> (Window os c ds, ContextColorOption c, DepthOption)) -> FragmentStream (FragColor c, FragDepth) -> Shader os s ()
drawWindowStencil :: forall os s c ds. StencilRenderable ds => (s -> (Window os c ds, StencilOptions)) -> FragmentStream () -> Shader os s ()
drawWindowColorStencil :: forall os s c ds. (ContextColorFormat c, StencilRenderable ds) => (s -> (Window os c ds, ContextColorOption c, StencilOptions)) -> FragmentStream (FragColor c) -> Shader os s ()
drawWindowDepthStencil :: forall os s c ds. (DepthRenderable ds, StencilRenderable ds) => (s -> (Window os c ds, DepthStencilOption)) -> FragmentStream FragDepth -> Shader os s ()
drawWindowColorDepthStencil :: forall os s c ds. (ContextColorFormat c, DepthRenderable ds, StencilRenderable ds) => (s -> (Window os c ds, ContextColorOption c, DepthStencilOption)) -> FragmentStream (FragColor c, FragDepth) -> Shader os s ()
drawWindowColor sf fs = Shader $ tellDrawcalls fs $ \ a -> make3 (setColor cf 0 a) io
where io s = let (w, op) = sf s in (Left (getWinName w), glDisable GL_DEPTH_TEST >> glDisable GL_STENCIL_TEST >> setGlContextColorOptions cf op)
cf = undefined :: c
drawWindowDepth sf fs = Shader $ tellDrawcalls fs $ \ a-> (setDepth a, return(), io)
where io s = let (w, op) = sf s in (Left (getWinName w), glDisable GL_STENCIL_TEST >> setGlDepthOptions op)
drawWindowColorDepth sf fs = Shader $ tellDrawcalls fs $ \(c,d) -> let (s, g) = setColor cf 0 c in (s >> setDepth d, g, io)
where io s = let (w, cop, dop) = sf s in (Left (getWinName w), glDisable GL_STENCIL_TEST >> setGlContextColorOptions cf cop >> setGlDepthOptions dop)
cf = undefined :: c
drawWindowStencil sf fs = Shader $ tellDrawcalls fs $ const (return (), return (), io)
where io s = let (w, op) = sf s in (Left (getWinName w), glDisable GL_DEPTH_TEST >> setGlStencilOptions op OpZero OpZero)
drawWindowColorStencil sf fs = Shader $ tellDrawcalls fs $ \ a -> make3 (setColor cf 0 a) io
where io s = let (w, cop, dop) = sf s in (Left (getWinName w), glDisable GL_DEPTH_TEST >> setGlContextColorOptions cf cop >> setGlStencilOptions dop OpZero OpZero)
cf = undefined :: c
drawWindowDepthStencil sf fs = Shader $ tellDrawcalls fs $ \ a-> (setDepth a, return(), io)
where io s = let (w, op) = sf s in (Left (getWinName w), setGlDepthStencilOptions op)
drawWindowColorDepthStencil sf fs = Shader $ tellDrawcalls fs $ \ (c,d) -> let (s, g) = setColor cf 0 c in (s >> setDepth d, g, io)
where io s = let (w, cop, dop) = sf s in (Left (getWinName w), setGlContextColorOptions cf cop >> setGlDepthStencilOptions dop)
cf = undefined :: c
tellDrawcalls :: FragmentStream a -> (a -> (ExprM (), GlobDeclM (), s -> (Either WinId (IO FBOKeys, IO ()), IO ()))) -> ShaderM s ()
tellDrawcalls (FragmentStream xs) f = do
let g (x, fd) = tellDrawcall $ makeDrawcall (f x) fd
mapM_ g xs
makeDrawcall :: (ExprM (), GlobDeclM (), s -> (Either WinId (IO FBOKeys, IO ()), IO ())) -> FragmentStreamData -> IO (Drawcall s)
makeDrawcall (sh, shd, wOrIo) (FragmentStreamData rastN shaderpos (PrimitiveStreamData primN ubuff) keep) =
do (fsource, funis, fsamps, _, prevDecls, prevS) <- runExprM shd (discard keep >> sh)
(vsource, vunis, vsamps, vinps, _, _) <- runExprM prevDecls (prevS >> shaderpos)
return $ Drawcall wOrIo primN rastN vsource fsource vinps vunis vsamps funis fsamps ubuff
setColor :: forall c. ColorSampleable c => c -> Int -> FragColor c -> (ExprM (), GlobDeclM ())
setColor ct n c = let name = "out" ++ show n
typeS = typeStr ct
in (do xs <- mapM unS (fromColor ct c :: [S F (ColorElement c)])
tellAssignment' name (typeS ++ "(" ++ intercalate "," xs ++ ")")
,
do tellGlobal "layout(location = "
tellGlobal $ show n
tellGlobal ") out "
tellGlobal typeS
tellGlobal " "
tellGlobalLn name)
setDepth :: FFloat -> ExprM ()
setDepth (S d) = do d' <- d
when (d' /= "gl_FragDepth") $
tellAssignment' "gl_FragDepth" d'
make3 :: (t, t1) -> t2 -> (t, t1, t2)
make3 (a,b) c = (a,b,c)
type FragColor c = Color c (S F (ColorElement c))
type FragDepth = FFloat
setGlColorMask :: ColorSampleable f => f -> GLuint -> Color f Bool -> IO ()
setGlColorMask c i mask = glColorMaski i x y z w
where [x,y,z,w] = map fromBool $ take 4 $ fromColor c mask ++ [False, False, False]
setGlContextColorOptions :: ColorSampleable f => f -> ContextColorOption f -> IO ()
setGlContextColorOptions c (ContextColorOption blend mask) = do
setGlColorMask c 0 mask
setGlBlend blend
case blend of
NoBlending -> glDisable GL_BLEND
LogicOp _ -> glDisable GL_BLEND
_ -> glEnable GL_BLEND
setGlBlend :: Blending -> IO ()
setGlBlend NoBlending = return ()
setGlBlend (BlendRgbAlpha (e, ea) (BlendingFactors sf df, BlendingFactors sfa dfa) (V4 r g b a)) = do
glBlendEquationSeparate (getGlBlendEquation e) (getGlBlendEquation ea)
glBlendFuncSeparate (getGlBlendFunc sf) (getGlBlendFunc df) (getGlBlendFunc sfa) (getGlBlendFunc dfa)
when (usesConstantColor sf || usesConstantColor df || usesConstantColor sfa || usesConstantColor dfa) $
glBlendColor (realToFrac r) (realToFrac g) (realToFrac b) (realToFrac a)
setGlBlend (LogicOp op) = glEnable GL_COLOR_LOGIC_OP >> glLogicOp (getGlLogicOp op)
setGlDepthOptions :: DepthOption -> IO ()
setGlDepthOptions (DepthOption df dm) = do glEnable GL_DEPTH_TEST
glDepthFunc (getGlCompFunc df)
glDepthMask $ fromBool dm
setGlStencilOptions :: FrontBack StencilOption -> StencilOp -> StencilOp -> IO ()
setGlStencilOptions (FrontBack (StencilOption ft fr ff fp frm fwm) (StencilOption bt br bf bp brm bwm)) fdf bdf = do
glEnable GL_STENCIL_TEST
glStencilFuncSeparate GL_FRONT (getGlCompFunc ft) (fromIntegral fr) (fromIntegral frm)
glStencilOpSeparate GL_FRONT (getGlStencilOp ff) (getGlStencilOp fdf) (getGlStencilOp fp)
glStencilMaskSeparate GL_FRONT (fromIntegral fwm)
glStencilFuncSeparate GL_BACK (getGlCompFunc bt) (fromIntegral br) (fromIntegral brm)
glStencilOpSeparate GL_BACK (getGlStencilOp bf) (getGlStencilOp bdf) (getGlStencilOp bp)
glStencilMaskSeparate GL_BACK (fromIntegral bwm)
setGlDepthStencilOptions :: DepthStencilOption -> IO ()
setGlDepthStencilOptions (DepthStencilOption sop dop (FrontBack fdf bdf)) = do
setGlDepthOptions dop
setGlStencilOptions sop fdf bdf
data ContextColorOption f = ContextColorOption Blending (ColorMask f)
data DepthOption = DepthOption DepthFunction DepthMask
type StencilOptions = FrontBack StencilOption
data StencilOption = StencilOption {
stencilTest :: ComparisonFunction,
stencilReference :: Int,
opWhenStencilFail :: StencilOp,
opWhenStencilPass :: StencilOp,
stencilReadBitMask :: Word,
stencilWriteBitMask :: Word
}
data DepthStencilOption = DepthStencilOption {
dsStencilOptions :: StencilOptions,
dsDepthOption :: DepthOption ,
opWhenStencilPassButDepthFail :: FrontBack StencilOp
}
data FrontBack a = FrontBack { front :: a, back :: a }
type ColorMask f = Color f Bool
type DepthMask = Bool
type DepthFunction = ComparisonFunction
type UseBlending = Bool
data Blending =
NoBlending
| BlendRgbAlpha (BlendEquation, BlendEquation) (BlendingFactors, BlendingFactors) ConstantColor
| LogicOp LogicOp
type ConstantColor = V4 Float
data BlendingFactors = BlendingFactors { blendFactorSrc :: BlendingFactor, blendFactorDst :: BlendingFactor }
data BlendEquation =
FuncAdd
| FuncSubtract
| FuncReverseSubtract
| Min
| Max
data BlendingFactor =
Zero
| One
| SrcColor
| OneMinusSrcColor
| DstColor
| OneMinusDstColor
| SrcAlpha
| OneMinusSrcAlpha
| DstAlpha
| OneMinusDstAlpha
| ConstantColor
| OneMinusConstantColor
| ConstantAlpha
| OneMinusConstantAlpha
| SrcAlphaSaturate
usesConstantColor ConstantColor = True
usesConstantColor OneMinusConstantColor = True
usesConstantColor ConstantAlpha = True
usesConstantColor OneMinusConstantAlpha = True
usesConstantColor _ = False
data LogicOp =
Clear
| And
| AndReverse
| Copy
| AndInverted
| Noop
| Xor
| Or
| Nor
| Equiv
| Invert
| OrReverse
| CopyInverted
| OrInverted
| Nand
| Set
data StencilOp =
OpZero
| OpKeep
| OpReplace
| OpIncr
| OpIncrWrap
| OpDecr
| OpDecrWrap
| OpInvert
clearImageColor :: forall c os. ColorRenderable c => Image (Format c) -> Color c (ColorElement c) -> Render os ()
clearImageColor i c = do (cwid, cd, doAsync) <- getLastRenderWin
key <- Render $ lift $ lift $ lift $ getImageFBOKey i
let fbokey = FBOKeys [key] Nothing Nothing
mfbo <- Render $ lift $ lift $ lift $ getFBO cd fbokey
case mfbo of
Just fbo -> Render $ liftIO $ doAsync $ do
fbo' <- readIORef fbo
glBindFramebuffer GL_DRAW_FRAMEBUFFER fbo'
Nothing -> Render $ maybeThrow $ liftIO $ asSync doAsync $ do
fbo' <- alloca (\ptr -> glGenFramebuffers 1 ptr >> peek ptr)
fbo <- newIORef fbo'
void $ mkWeakIORef fbo (doAsync $ with fbo' $ glDeleteFramebuffers 1)
setFBO cd fbokey fbo
glBindFramebuffer GL_DRAW_FRAMEBUFFER fbo'
glEnable GL_FRAMEBUFFER_SRGB
getImageBinding i GL_COLOR_ATTACHMENT0
withArray [GL_COLOR_ATTACHMENT0] $ glDrawBuffers 1
getFBOerror
Render $ liftIO $ doAsync $ do
glDisable GL_SCISSOR_TEST
glColorMask glTrue glTrue glTrue glTrue
clearColor (undefined :: c) c
glEnable GL_SCISSOR_TEST
clearImageDepth :: DepthRenderable d => Image (Format d) -> Float -> Render os ()
clearImageDepth i d = do (cwid, cd, doAsync) <- getLastRenderWin
key <- Render $ lift $ lift $ lift $ getImageFBOKey i
let fbokey = FBOKeys [] (Just key) Nothing
mfbo <- Render $ lift $ lift $ lift $ getFBO cd fbokey
case mfbo of
Just fbo -> Render $ liftIO $ doAsync $ do
fbo' <- readIORef fbo
glBindFramebuffer GL_DRAW_FRAMEBUFFER fbo'
Nothing -> Render $ maybeThrow $ liftIO $ asSync doAsync $ do
fbo' <- alloca (\ptr -> glGenFramebuffers 1 ptr >> peek ptr)
fbo <- newIORef fbo'
void $ mkWeakIORef fbo (doAsync $ with fbo' $ glDeleteFramebuffers 1)
setFBO cd fbokey fbo
glBindFramebuffer GL_DRAW_FRAMEBUFFER fbo'
glEnable GL_FRAMEBUFFER_SRGB
getImageBinding i GL_DEPTH_ATTACHMENT
glDrawBuffers 0 nullPtr
getFBOerror
Render $ liftIO $ doAsync $ do
glDisable GL_SCISSOR_TEST
glDepthMask glTrue
with (realToFrac d) $ glClearBufferfv GL_DEPTH 0
glEnable GL_SCISSOR_TEST
clearImageStencil :: StencilRenderable s => Image (Format s) -> Int -> Render os ()
clearImageStencil i s = do (cwid, cd, doAsync) <- getLastRenderWin
key <- Render $ lift $ lift $ lift $ getImageFBOKey i
let fbokey = FBOKeys [] Nothing (Just key)
mfbo <- Render $ lift $ lift $ lift $ getFBO cd fbokey
case mfbo of
Just fbo -> Render $ liftIO $ doAsync $ do
fbo' <- readIORef fbo
glBindFramebuffer GL_DRAW_FRAMEBUFFER fbo'
Nothing -> Render $ maybeThrow $ liftIO $ asSync doAsync $ do
fbo' <- alloca (\ptr -> glGenFramebuffers 1 ptr >> peek ptr)
fbo <- newIORef fbo'
void $ mkWeakIORef fbo (doAsync $ with fbo' $ glDeleteFramebuffers 1)
setFBO cd fbokey fbo
glBindFramebuffer GL_DRAW_FRAMEBUFFER fbo'
glEnable GL_FRAMEBUFFER_SRGB
getImageBinding i GL_STENCIL_ATTACHMENT
glDrawBuffers 0 nullPtr
getFBOerror
Render $ liftIO $ doAsync $ do
glDisable GL_SCISSOR_TEST
glStencilMask maxBound
with (fromIntegral s) $ glClearBufferiv GL_STENCIL 0
glEnable GL_SCISSOR_TEST
clearImageDepthStencil :: Image (Format DepthStencil) -> Float -> Int -> Render os ()
clearImageDepthStencil i d s = do
(cwid, cd, doAsync) <- getLastRenderWin
key <- Render $ lift $ lift $ lift $ getImageFBOKey i
let fbokey = FBOKeys [] Nothing (Just key)
mfbo <- Render $ lift $ lift $ lift $ getFBO cd fbokey
case mfbo of
Just fbo -> Render $ liftIO $ doAsync $ do
fbo' <- readIORef fbo
glBindFramebuffer GL_DRAW_FRAMEBUFFER fbo'
Nothing -> Render $ maybeThrow $ liftIO $ asSync doAsync $ do
fbo' <- alloca (\ptr -> glGenFramebuffers 1 ptr >> peek ptr)
fbo <- newIORef fbo'
void $ mkWeakIORef fbo (doAsync $ with fbo' $ glDeleteFramebuffers 1)
setFBO cd fbokey fbo
glBindFramebuffer GL_DRAW_FRAMEBUFFER fbo'
glEnable GL_FRAMEBUFFER_SRGB
getImageBinding i GL_DEPTH_STENCIL_ATTACHMENT
glDrawBuffers 0 nullPtr
getFBOerror
Render $ liftIO $ doAsync $ do
glDisable GL_SCISSOR_TEST
glDepthMask glTrue
glStencilMask maxBound
glClearBufferfi GL_DEPTH_STENCIL 0 (realToFrac d) (fromIntegral s)
glEnable GL_SCISSOR_TEST
inWin w m = Render $ do
rs <- lift $ lift StrictState.get
case IMap.lookup (getWinName w) (perWindowRenderState rs) of
Nothing -> return ()
Just (_, doAsync) -> liftIO $ doAsync m
clearWindowColor :: forall os c ds. ContextColorFormat c => Window os c ds -> Color c Float -> Render os ()
clearWindowColor w c = inWin w $ do
glBindFramebuffer GL_DRAW_FRAMEBUFFER 0
glDisable GL_SCISSOR_TEST
glColorMask glTrue glTrue glTrue glTrue
withArray (map realToFrac (fromColor (undefined :: c) c ++ replicate 3 0 :: [Float])) $ glClearBufferfv GL_COLOR 0
glEnable GL_SCISSOR_TEST
clearWindowDepth :: DepthRenderable ds => Window os c ds -> Float -> Render os ()
clearWindowDepth w d = inWin w $ do
glBindFramebuffer GL_DRAW_FRAMEBUFFER 0
glDisable GL_SCISSOR_TEST
glDepthMask glTrue
with (realToFrac d) $ glClearBufferfv GL_DEPTH 0
glEnable GL_SCISSOR_TEST
clearWindowStencil :: StencilRenderable ds => Window os c ds -> Int -> Render os ()
clearWindowStencil w s = inWin w $ do
glBindFramebuffer GL_DRAW_FRAMEBUFFER 0
glDisable GL_SCISSOR_TEST
glStencilMask maxBound
with (fromIntegral s) $ glClearBufferiv GL_STENCIL 0
glEnable GL_SCISSOR_TEST
clearWindowDepthStencil :: Window os c DepthStencil -> Float -> Int -> Render os ()
clearWindowDepthStencil w d s = inWin w $ do
glBindFramebuffer GL_DRAW_FRAMEBUFFER 0
glDisable GL_SCISSOR_TEST
glDepthMask glTrue
glStencilMask maxBound
glClearBufferfi GL_DEPTH_STENCIL 0 (realToFrac d) (fromIntegral s)
glEnable GL_SCISSOR_TEST
maybeThrow :: Monad m => ExceptT e m (Maybe e) -> ExceptT e m ()
maybeThrow m = do mErr <- m
case mErr of
Just err -> throwE err
Nothing -> return ()
glTrue :: Num n => n
glTrue = fromBool True
getGlBlendEquation :: BlendEquation -> GLenum
getGlBlendEquation FuncAdd = GL_FUNC_ADD
getGlBlendEquation FuncSubtract = GL_FUNC_SUBTRACT
getGlBlendEquation FuncReverseSubtract = GL_FUNC_REVERSE_SUBTRACT
getGlBlendEquation Min = GL_MIN
getGlBlendEquation Max = GL_MAX
getGlBlendFunc :: BlendingFactor -> GLenum
getGlBlendFunc Zero = GL_ZERO
getGlBlendFunc One = GL_ONE
getGlBlendFunc SrcColor = GL_SRC_COLOR
getGlBlendFunc OneMinusSrcColor = GL_ONE_MINUS_SRC_COLOR
getGlBlendFunc DstColor = GL_DST_COLOR
getGlBlendFunc OneMinusDstColor = GL_ONE_MINUS_DST_COLOR
getGlBlendFunc SrcAlpha = GL_SRC_ALPHA
getGlBlendFunc OneMinusSrcAlpha = GL_ONE_MINUS_SRC_ALPHA
getGlBlendFunc DstAlpha = GL_DST_ALPHA
getGlBlendFunc OneMinusDstAlpha = GL_ONE_MINUS_DST_ALPHA
getGlBlendFunc ConstantColor = GL_CONSTANT_COLOR
getGlBlendFunc OneMinusConstantColor = GL_ONE_MINUS_CONSTANT_COLOR
getGlBlendFunc ConstantAlpha = GL_CONSTANT_ALPHA
getGlBlendFunc OneMinusConstantAlpha = GL_ONE_MINUS_CONSTANT_ALPHA
getGlBlendFunc SrcAlphaSaturate = GL_SRC_ALPHA_SATURATE
getGlLogicOp :: LogicOp -> GLenum
getGlLogicOp Clear = GL_CLEAR
getGlLogicOp And = GL_AND
getGlLogicOp AndReverse = GL_AND_REVERSE
getGlLogicOp Copy = GL_COPY
getGlLogicOp AndInverted = GL_AND_INVERTED
getGlLogicOp Noop = GL_NOOP
getGlLogicOp Xor = GL_XOR
getGlLogicOp Or = GL_OR
getGlLogicOp Nor = GL_NOR
getGlLogicOp Equiv = GL_EQUIV
getGlLogicOp Invert = GL_INVERT
getGlLogicOp OrReverse = GL_OR_REVERSE
getGlLogicOp CopyInverted = GL_COPY_INVERTED
getGlLogicOp OrInverted = GL_OR_INVERTED
getGlLogicOp Nand = GL_NAND
getGlLogicOp Set = GL_SET
getGlStencilOp :: StencilOp -> GLenum
getGlStencilOp OpZero = GL_ZERO
getGlStencilOp OpKeep = GL_KEEP
getGlStencilOp OpReplace = GL_REPLACE
getGlStencilOp OpIncr = GL_INCR
getGlStencilOp OpIncrWrap = GL_INCR_WRAP
getGlStencilOp OpDecr = GL_DECR
getGlStencilOp OpDecrWrap = GL_DECR_WRAP
getGlStencilOp OpInvert = GL_INVERT