-------------------------------------------------------------------------------- -- | -- Module : Graphics.Rendering.OpenGL.GL.DisplayLists -- Copyright : (c) Sven Panne 2002-2006 -- License : BSD-style (see the file libraries/OpenGL/LICENSE) -- -- Maintainer : sven.panne@aedion.de -- Stability : stable -- Portability : portable -- -- This module corresponds to section 5.4 (Display Lists) of the OpenGL 2.1 -- specs. -- -------------------------------------------------------------------------------- module Graphics.Rendering.OpenGL.GL.DisplayLists ( -- * Defining Display Lists DisplayList(..), ListMode(..), defineList, defineNewList, listIndex, listMode, maxListNesting, -- * Calling Display Lists callList, callLists, listBase, -- * Deprecated Functions genLists, deleteLists, isList, ) where import Foreign.Ptr ( Ptr ) import Graphics.Rendering.OpenGL.GL.BasicTypes ( GLboolean, GLuint, GLsizei, GLenum ) import Graphics.Rendering.OpenGL.GL.BufferObjects ( ObjectName(..) ) import Graphics.Rendering.OpenGL.GL.DataType ( marshalDataType ) import Graphics.Rendering.OpenGL.GL.VertexArrays ( DataType ) import Graphics.Rendering.OpenGL.GL.Exception ( bracket_ ) import Graphics.Rendering.OpenGL.GL.GLboolean ( unmarshalGLboolean ) import Graphics.Rendering.OpenGL.GL.QueryUtils ( GetPName(GetListIndex,GetListMode,GetMaxListNesting,GetListBase), getEnum1, getSizei1 ) import Graphics.Rendering.OpenGL.GL.StateVar ( GettableStateVar, makeGettableStateVar, StateVar, makeStateVar ) import Graphics.Rendering.OpenGL.GLU.ErrorsInternal ( recordOutOfMemory ) -------------------------------------------------------------------------------- newtype DisplayList = DisplayList GLuint deriving ( Eq, Ord, Show ) instance ObjectName DisplayList where genObjectNames = genLists_ deleteObjectNames = deleteLists_ isObjectName = isList_ -------------------------------------------------------------------------------- {-# DEPRECATED genLists "use `genObjectNames' instead" #-} genLists :: GLsizei -> IO [DisplayList] genLists = genLists_ . fromIntegral genLists_ :: Int -> IO [DisplayList] genLists_ n = do first <- glGenLists (fromIntegral n) if DisplayList first == noDisplayList then do recordOutOfMemory return [] else return [ DisplayList l | l <- [ first .. first + fromIntegral n - 1 ] ] foreign import CALLCONV unsafe "glGenLists" glGenLists :: GLsizei -> IO GLuint -------------------------------------------------------------------------------- {-# DEPRECATED deleteLists "use `deleteObjectNames' instead" #-} deleteLists :: [DisplayList] -> IO () deleteLists = deleteLists_ deleteLists_ :: [DisplayList] -> IO () deleteLists_ = mapM_ (uncurry glDeleteLists) . combineConsecutive foreign import CALLCONV unsafe "glDeleteLists" glDeleteLists :: DisplayList -> GLsizei -> IO () combineConsecutive :: [DisplayList] -> [(DisplayList, GLsizei)] combineConsecutive [] = [] combineConsecutive (z:zs) = (z, len) : combineConsecutive rest where (len, rest) = run (0 :: GLsizei) z zs run n x xs = case n + 1 of m -> case xs of [] -> (m, []) (y:ys) | x `isFollowedBy` y -> run m y ys | otherwise -> (m, xs) DisplayList x `isFollowedBy` DisplayList y = x + 1 == y -------------------------------------------------------------------------------- {-# DEPRECATED isList "use `isObjectName' instead" #-} isList :: DisplayList -> IO Bool isList = isList_ isList_ :: DisplayList -> IO Bool isList_ = fmap unmarshalGLboolean . glIsList foreign import CALLCONV unsafe "glIsList" glIsList :: DisplayList -> IO GLboolean -------------------------------------------------------------------------------- data ListMode = Compile | CompileAndExecute deriving ( Eq, Ord, Show ) marshalListMode :: ListMode -> GLenum marshalListMode x = case x of Compile -> 0x1300 CompileAndExecute -> 0x1301 unmarshalListMode :: GLenum -> ListMode unmarshalListMode x | x == 0x1300 = Compile | x == 0x1301 = CompileAndExecute | otherwise = error ("unmarshalListMode: illegal value " ++ show x) -------------------------------------------------------------------------------- defineList :: DisplayList -> ListMode -> IO a -> IO a defineList lst mode = bracket_ (glNewList lst (marshalListMode mode)) glEndList foreign import CALLCONV unsafe "glNewList" glNewList :: DisplayList -> GLenum -> IO () foreign import CALLCONV unsafe "glEndList" glEndList :: IO () defineNewList :: ListMode -> IO a -> IO DisplayList defineNewList mode action = do lists <- genLists 1 if null lists then do recordOutOfMemory return noDisplayList else do let lst = head lists defineList lst mode action return lst -------------------------------------------------------------------------------- listIndex :: GettableStateVar (Maybe DisplayList) listIndex = makeGettableStateVar (do l <- getEnum1 DisplayList GetListIndex return $ if l == noDisplayList then Nothing else Just l) noDisplayList :: DisplayList noDisplayList = DisplayList 0 listMode :: GettableStateVar ListMode listMode = makeGettableStateVar (getEnum1 unmarshalListMode GetListMode) maxListNesting :: GettableStateVar GLsizei maxListNesting = makeGettableStateVar (getSizei1 id GetMaxListNesting) -------------------------------------------------------------------------------- foreign import CALLCONV unsafe "glCallList" callList :: DisplayList -> IO () callLists :: GLsizei -> DataType -> Ptr a -> IO () callLists n = glCallLists n . marshalDataType foreign import CALLCONV unsafe "glCallLists" glCallLists :: GLsizei -> GLenum -> Ptr a -> IO () -------------------------------------------------------------------------------- listBase :: StateVar DisplayList listBase = makeStateVar (getEnum1 DisplayList GetListBase) glListBase foreign import CALLCONV unsafe "glListBase" glListBase :: DisplayList -> IO ()