module Graphics.GLUtil.BufferObjects where
import Data.Word (Word32)
import Graphics.Rendering.OpenGL
import Foreign.ForeignPtr
import Foreign.Ptr
import Foreign.Storable
import Data.Array.Storable
import qualified Data.Vector.Storable as V
import Data.ByteString (ByteString, useAsCStringLen)
makeBuffer :: Storable a => BufferTarget -> [a] -> IO BufferObject
makeBuffer target elems = makeBufferLen target (length elems) elems
makeBufferLen :: forall a. Storable a =>
BufferTarget -> Int -> [a] -> IO BufferObject
makeBufferLen target len elems =
do [buffer] <- genObjectNames 1
bindBuffer target $= Just buffer
let n = fromIntegral $ len * sizeOf (undefined::a)
arr <- newListArray (0, len 1) elems
withStorableArray arr $ \ptr ->
bufferData target $= (n, ptr, StaticDraw)
return buffer
replaceBuffer :: forall a. Storable a => BufferTarget -> [a] -> IO ()
replaceBuffer target elems = do arr <- newListArray (0, len 1) elems
withStorableArray arr $ \ptr ->
bufferData target $= (n, ptr, StaticDraw)
where len = length elems
n = fromIntegral $ len * sizeOf (undefined::a)
fromPtr :: BufferTarget -> Int -> Ptr a -> IO BufferObject
fromPtr target numBytes ptr =
do [buffer] <- genObjectNames 1
bindBuffer target $= Just buffer
bufferData target $= (fromIntegral numBytes, ptr, StaticDraw)
return buffer
fromByteString :: BufferTarget -> ByteString -> IO BufferObject
fromByteString target b = useAsCStringLen b (uncurry . flip $ fromPtr target)
fromForeignPtr :: forall a. Storable a =>
BufferTarget -> Int -> ForeignPtr a -> IO BufferObject
fromForeignPtr target len fptr = withForeignPtr fptr $ fromPtr target numBytes
where numBytes = sizeOf (undefined::a) * len
fromVector :: forall a. Storable a =>
BufferTarget -> V.Vector a -> IO BufferObject
fromVector target v = V.unsafeWith v $ fromPtr target numBytes
where numBytes = fromIntegral $ V.length v * sizeOf (undefined::a)
replaceVector :: forall a. Storable a => BufferTarget -> V.Vector a -> IO ()
replaceVector target v = V.unsafeWith v $ \ptr ->
bufferData target $= (numBytes, ptr, StaticDraw)
where numBytes = fromIntegral $ V.length v * sizeOf (undefined::a)
offsetPtr :: Int -> Ptr a
offsetPtr = wordPtrToPtr . fromIntegral
offset0 :: Ptr a
offset0 = offsetPtr 0
class BufferSource v where
fromSource :: BufferTarget -> v -> IO BufferObject
instance Storable a => BufferSource [a] where
fromSource = makeBuffer
instance Storable a => BufferSource (V.Vector a) where
fromSource = fromVector
bufferIndices :: BufferSource (v Word32) => v Word32 -> IO BufferObject
bufferIndices = fromSource ElementArrayBuffer