{-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE PatternSynonyms #-} -- | If you issue an invalid GL command or run out of memory, the GL -- implementation may set an internal flag indicating that an error has -- occurred. You can query this flag ('getGLError') to see if something went -- wrong with a previous command. If you ignore errors, chances are nothing -- will happen except perhaps some rendering weirdness. However checking this -- periodically is a good idea, perhaps once per frame, because it might -- indicate a bug in your code. module Graphics.GL.Low.Error ( GLError(..), getGLError, assertNoGLError, ) where import Control.Exception import Data.Typeable import Graphics.GL -- | Detectable errors. data GLError = InvalidEnum | -- ^ Enum argument out of range. InvalidValue | -- ^ Integer argument out of range. InvalidOperation | -- ^ Operation illegal in current state. InvalidFramebufferOperation | -- ^ Framebuffer is not complete. OutOfMemory deriving Typeable instance Exception GLError instance Show GLError where show InvalidEnum = "INVALID_ENUM enum argument out of range" show InvalidValue = "INVALID_VALUE Numeric argument out of range" show InvalidOperation = "INVALID_OPERATION Illegal in current state" show InvalidFramebufferOperation = "INVALID_FRAMEBUFFER_OPERATION Framebuffer object is not complete" show OutOfMemory = "Not enough memory left to execute command" -- | Check for a GL Error. This call has the semantics of a dequeue. If an -- error is returned, then calling getGLError again may return more errors that -- have "stacked up." When it returns Nothing then there are no more errors to -- report. An error indicates that a bug in your code caused incorrect ussage -- of the API or that the implementation has run out of memory. -- -- It has been suggested that using this after every single GL command may -- adversely affect performance (not to mention be very tedious). Since there -- is no reasonable way to recover from a GL error, a good idea might be to -- check this once per frame or even less often, and respond with a core dump. getGLError :: IO (Maybe GLError) getGLError = do n <- glGetError return $ case n of GL_NO_ERROR -> Nothing GL_INVALID_ENUM -> Just InvalidEnum GL_INVALID_VALUE -> Just InvalidValue GL_INVALID_OPERATION -> Just InvalidOperation GL_INVALID_FRAMEBUFFER_OPERATION -> Just InvalidFramebufferOperation GL_OUT_OF_MEMORY -> Just OutOfMemory _ -> error ("unknown GL error " ++ show n) -- | Throws an exception if 'getGLError' returns non-Nothing. assertNoGLError :: IO () assertNoGLError = do me <- getGLError case me of Nothing -> return () Just e -> throwIO e