aboutsummaryrefslogtreecommitdiff
path: root/Graphics/Glyph/ExtendedGL/Base.hs
blob: 88566f45364b817cf909f0241918dccf50da96f0 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE MultiParamTypeClasses #-}
module Graphics.Glyph.ExtendedGL.Base where

import qualified Graphics.Rendering.OpenGL as GL
import Graphics.GL.Core43
import Graphics.GL.Compatibility30

import Foreign.Marshal.Alloc
import Foreign.Ptr
import Foreign.Storable
import Foreign.C.Types

import System.IO.Unsafe
import Control.Monad

import Data.StateVar
import Unsafe.Coerce
import Data.Proxy

data ExPrimitiveMode = Points | Triangles | Lines | Patches deriving (Show,Enum)

class IsBindable a where
    bind :: a -> IO ()
class IsGLEnumMarshallable a where
    toGLEnum :: a -> GLenum
class IsGenerable a where
    generate :: IO a
class IsWrappedPrimitive t a where
    unwrap :: a -> t
    wrap :: t -> a
class HasIntegerParam t a where
    parami :: t -> a -> SettableStateVar GLuint
class HasFloatParam t a where
    paramf :: t -> a -> SettableStateVar GLfloat
class HasParamOfType b t a where
    param :: t -> a -> SettableStateVar b

class IsPrimitiveModeMarshallable a where
    marshalPrimitiveMode :: a -> GLuint

castPrimitive :: forall a b t. (IsWrappedPrimitive t a, IsWrappedPrimitive t b) => Proxy t -> a -> b
castPrimitive _ x = wrap unw
    where
        unw :: t
        unw = unwrap x

instance (IsWrappedPrimitive a a) where
    unwrap = id
    wrap = id
instance (IsWrappedPrimitive GLenum a) => IsGLEnumMarshallable a where
    toGLEnum = unwrap

instance IsPrimitiveModeMarshallable ExPrimitiveMode where
    marshalPrimitiveMode x = case x of
        Points    -> GL_POINTS
        Triangles -> GL_TRIANGLES
        Lines     -> GL_LINES
        Patches   -> GL_PATCHES

instance IsPrimitiveModeMarshallable GL.PrimitiveMode where
    marshalPrimitiveMode x = case x of
        GL.Points -> 0x0
        GL.Lines -> 0x1
        GL.LineLoop -> 0x2
        GL.LineStrip -> 0x3
        GL.Triangles -> 0x4
        GL.TriangleStrip -> 0x5
        GL.TriangleFan -> 0x6
        GL.Quads -> 0x7
        GL.QuadStrip -> 0x8
        GL.Polygon -> 0x9

instance IsPrimitiveModeMarshallable GLuint where
    marshalPrimitiveMode = id

vertexAttributeDivisor :: GL.AttribLocation -> SettableStateVar GLuint
vertexAttributeDivisor (GL.AttribLocation loc) =
    makeSettableStateVar $ \val ->
        glVertexAttribDivisor loc val

{- Sets the number of vertices per patch
 - for OpenGL -}
patchVertices :: (Integral a) => SettableStateVar a
patchVertices = 
    makeSettableStateVar $ \val ->
        glPatchParameteri GL_PATCH_VERTICES $ fromIntegral val

{- Returns the maximum number of patches
 - for a tessilation shader -}
maxPatchVertices :: IO CInt
maxPatchVertices =
        alloca $ \ptr -> do
            glGetIntegerv GL_MAX_PATCH_VERTICES ptr
            fromIntegral <$> peek ptr

getGLVersion :: IO String
getGLVersion =
    let lift2 (a,b) = do
            x <- a ; y <- b ; return (x,y)
             in
    alloca $ \ptr1 -> alloca $ \ptr2 -> do
        glGetIntegerv GL_MAJOR_VERSION ptr1
        glGetIntegerv GL_MINOR_VERSION ptr2
        (v1,v2) <- lift2 (peek ptr1, peek ptr2)
        return ("OpenGL " ++ show v1 ++ "." ++ show v2)

coerced :: a
coerced = unsafeCoerce (0::Int)