summaryrefslogtreecommitdiff
path: root/PointPrimitiveRing.hs
blob: d4fafaefbe7fc61529f1eeed469ff5b736efa062 (plain)
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
{-# LANGUAGE LambdaCase, RecordWildCards, DataKinds #-}
module PointPrimitiveRing where

import Control.Monad
import Control.Monad.Writer
import Data.Data
import Data.Dependent.Sum
import Data.Foldable
import Data.Function
import Data.Int
import Data.IORef
import Data.Maybe
import Data.Some
import Data.Word
import qualified Data.Map.Strict as Map
import qualified Data.Vector as V
         ;import Data.Vector as V ((!),(//))
import Foreign.C.Types (CPtrdiff)
import Foreign.Marshal
import Foreign.Ptr
import Foreign.Storable

import LambdaCube.GL      as LC
import LambdaCube.GL.Data -- (uploadCubeMapToGPU,uploadTextureBufferToGPU,updateTextureBuffer)
import LambdaCube.GL.Mesh as LC
import LambdaCube.GL.Type
import LambdaCube.IR      as LC
import LambdaCube.GL.Util
import LambdaCube.GL.Input.Type
import LambdaCube.GL.Input hiding (createObjectCommands)

import AttributeData

-- import Graphics.GL.Core33

import MaskableStream

data Ring keys = Ring
    { rBufferObject :: Buffer
    , rStorage      :: GLStorage
    , rObject       :: Object
    , rSize         :: IORef Int -- Current count of vertices in the ring buffer.
    , rBack         :: IORef Int -- Where next vertex will be added.
    , ringCapacity  :: Int       -- Maximum number of vertices in buffer.
    , rKeys         :: keys
    }

newRing :: Data keys => GLStorage -> Int -> (String -> String) -> IO (Ring keys)
newRing storage sz toAttr = fix $ \retProxy -> do
    let paramProxy = paramProxy' retProxy
            where paramProxy' :: io (ring keys) -> Proxy keys
                  paramProxy' _ = Proxy
    startRef <- newIORef 0
    sizeRef <- newIORef 0
    let ps = fieldParameters paramProxy toAttr
    putStrLn $ "Ring params: " ++ show ps
    gd0 <- uploadDynamicBuffer sz ps
    let gd = gd0 { dPrimitive = LineStrip }
    Just keys <- return $ lookupAttrKeys (lookupAttributeKey gd . toAttr)
    obj <- addToObjectArray storage "Points" [] gd
    readIORef (objCommands obj) >>= mapM_ print
    let r = Ring
            { rBufferObject = streamBuffer $ head $ Map.elems (dStreams gd)
            , rStorage      = storage
            , rObject       = obj
            , rSize         = sizeRef
            , rBack         = startRef
            , ringCapacity  = sz
            , rKeys         = keys
            }
    updateRingCommands r
    return r

clearRing :: Ring keys -> IO ()
clearRing r = do
    writeIORef (rBack r) 0
    writeIORef (rSize r) 0
    updateRingCommands r

updateRingCommands :: Ring keys -> IO ()
updateRingCommands r = do
    back <- fromIntegral <$> readIORef (rBack r)
    size  <- fromIntegral <$> readIORef (rSize r)
    let mask 0   = []
        mask cnt
            | cnt==size = [(0,cnt)]
            | otherwise = case cnt + back - size of
                front | front > cnt -> [(front - cnt,size)]
                      | otherwise   -> [(0,back), (front,cnt - front)]
    updateCommands (rStorage r) (rObject r) mask
    -- readIORef (objCommands $ rObject r) >>= mapM_ print
    return ()

pushBack :: Ring keys -> (keys -> Writer [DSum AttributeKey GLUniformValue] a) -> IO ()
pushBack r attrs = do
    back <- readIORef $ rBack r
    writeIORef (rBack r) (mod (back + 1) (ringCapacity r))
    updateAttributes back $ attrs (rKeys r)
    sz <- readIORef (rSize r)
    when (sz < ringCapacity r) $ writeIORef (rSize r) (sz + 1)
    updateRingCommands r

updateBack :: Ring keys -> (keys -> Writer [DSum AttributeKey GLUniformValue] a) -> IO ()
updateBack r attrs = do
    back <- readIORef $ rBack r
    updateAttributes (mod (back - 1) (ringCapacity r)) $ attrs (rKeys r)

updateRingUniforms :: GLStorage -> Ring keys -> IO ()
updateRingUniforms _ _ = return ()