-------------------------------------------------------------------------------- -- | -- Module : Graphics.Rendering.OpenGL.GL.DisplayLists -- Copyright : (c) Sven Panne 2002-2009 -- 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 Data.ObjectName import Data.StateVar import Foreign.Ptr import Graphics.Rendering.OpenGL.GL.DataType import Graphics.Rendering.OpenGL.GL.Exception import Graphics.Rendering.OpenGL.GL.GLboolean import Graphics.Rendering.OpenGL.GL.QueryUtils import Graphics.Rendering.OpenGL.GLU.ErrorsInternal import Graphics.Rendering.OpenGL.Raw.ARB.Compatibility ( glCallList, glCallLists, glDeleteLists, glEndList, glGenLists, glIsList, glListBase, glNewList, gl_COMPILE, gl_COMPILE_AND_EXECUTE ) import Graphics.Rendering.OpenGL.Raw.Core31 -------------------------------------------------------------------------------- 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 ] ] -------------------------------------------------------------------------------- {-# DEPRECATED deleteLists "use `deleteObjectNames' instead" #-} deleteLists :: [DisplayList] -> IO () deleteLists = deleteLists_ deleteLists_ :: [DisplayList] -> IO () deleteLists_ = mapM_ (uncurry glDeleteLists) . combineConsecutive combineConsecutive :: [DisplayList] -> [(GLuint, GLsizei)] combineConsecutive [] = [] combineConsecutive (z@(DisplayList dl) :zs) = (dl, 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_ (DisplayList dl) = fmap unmarshalGLboolean (glIsList dl) -------------------------------------------------------------------------------- data ListMode = Compile | CompileAndExecute deriving ( Eq, Ord, Show ) marshalListMode :: ListMode -> GLenum marshalListMode x = case x of Compile -> gl_COMPILE CompileAndExecute -> gl_COMPILE_AND_EXECUTE unmarshalListMode :: GLenum -> ListMode unmarshalListMode x | x == gl_COMPILE = Compile | x == gl_COMPILE_AND_EXECUTE = CompileAndExecute | otherwise = error ("unmarshalListMode: illegal value " ++ show x) -------------------------------------------------------------------------------- defineList :: DisplayList -> ListMode -> IO a -> IO a defineList (DisplayList dl) mode = bracket_ (glNewList dl (marshalListMode mode)) glEndList 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 . fromIntegral) 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) -------------------------------------------------------------------------------- callList :: DisplayList -> IO () callList (DisplayList dl) = glCallList dl callLists :: GLsizei -> DataType -> Ptr a -> IO () callLists n = glCallLists n . marshalDataType -------------------------------------------------------------------------------- listBase :: StateVar DisplayList listBase = makeStateVar (getEnum1 (DisplayList . fromIntegral) GetListBase) (\(DisplayList dl) -> glListBase dl)