module Graphics.Rendering.OpenGL.GL.SyncObjects (
SyncObject, syncGpuCommandsComplete,
WaitTimeout, WaitFlag(..), WaitResult(..), clientWaitSync,
waitSync, maxServerWaitTimeout,
SyncStatus(..), syncStatus
) where
import Control.Monad.IO.Class
import Data.ObjectName
import Data.StateVar
import Foreign.Marshal.Utils ( with )
import Foreign.Ptr ( nullPtr )
import Graphics.Rendering.OpenGL.GL.DebugOutput
import Graphics.Rendering.OpenGL.GL.GLboolean
import Graphics.Rendering.OpenGL.GL.PeekPoke
import Graphics.Rendering.OpenGL.GL.QueryUtils
import Graphics.GL
newtype SyncObject = SyncObject { syncID :: GLsync }
deriving ( Eq, Ord, Show )
instance ObjectName SyncObject where
isObjectName = liftIO . fmap unmarshalGLboolean . glIsSync . syncID
deleteObjectName = liftIO . glDeleteSync . syncID
instance CanBeLabeled SyncObject where
objectLabel = objectPtrLabel . syncID
syncGpuCommandsComplete :: IO SyncObject
syncGpuCommandsComplete =
fmap SyncObject $ glFenceSync GL_SYNC_GPU_COMMANDS_COMPLETE 0
type WaitTimeout = GLuint64
data WaitFlag = SyncFlushCommands
deriving ( Eq, Ord, Show )
marshalWaitFlag :: WaitFlag -> GLbitfield
marshalWaitFlag x = case x of
SyncFlushCommands -> GL_SYNC_FLUSH_COMMANDS_BIT
data WaitResult =
AlreadySignaled
| TimeoutExpired
| ConditionSatisfied
| WaitFailed
deriving ( Eq, Ord, Show )
unmarshalWaitResult :: GLenum -> WaitResult
unmarshalWaitResult x
| x == GL_ALREADY_SIGNALED = AlreadySignaled
| x == GL_TIMEOUT_EXPIRED = TimeoutExpired
| x == GL_CONDITION_SATISFIED = ConditionSatisfied
| x == GL_WAIT_FAILED = WaitFailed
| otherwise = error ("unmarshalWaitResult: illegal value " ++ show x)
clientWaitSync :: SyncObject -> [WaitFlag] -> WaitTimeout -> IO WaitResult
clientWaitSync syncObject flags =
fmap unmarshalWaitResult .
glClientWaitSync (syncID syncObject) (sum (map marshalWaitFlag flags))
waitSync :: SyncObject -> IO ()
waitSync syncObject =
glWaitSync (syncID syncObject) 0 (fromIntegral GL_TIMEOUT_IGNORED)
maxServerWaitTimeout :: GettableStateVar WaitTimeout
maxServerWaitTimeout =
makeGettableStateVar (getInteger64 fromIntegral GetMaxServerWaitTimeout)
data SyncStatus =
Unsignaled
| Signaled
deriving ( Eq, Ord, Show )
unmarshalSyncStatus :: GLenum -> SyncStatus
unmarshalSyncStatus x
| x == GL_UNSIGNALED = Unsignaled
| x == GL_SIGNALED = Signaled
| otherwise = error ("unmarshalSyncStatus: illegal value " ++ show x)
syncStatus :: SyncObject -> GettableStateVar SyncStatus
syncStatus syncObject =
makeGettableStateVar $
with 0 $ \buf -> do
glGetSynciv (syncID syncObject) GL_SYNC_STATUS 1 nullPtr buf
peek1 (unmarshalSyncStatus . fromIntegral) buf