summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCsaba Hruska <csaba.hruska@gmail.com>2016-12-24 21:20:02 +0100
committerCsaba Hruska <csaba.hruska@gmail.com>2016-12-24 21:20:02 +0100
commitd15e800d66d74a5ec819f291cc7cfb5ddcb28d81 (patch)
treee377c6a2be162c08e319b76c3bec5b57ddf60e24
parent5332c0ae54eeb591762e0b348d2fcf8132988b1d (diff)
some render optimization
-rw-r--r--src/LambdaCube/GL/Backend.hs254
-rw-r--r--src/LambdaCube/GL/Type.hs50
2 files changed, 202 insertions, 102 deletions
diff --git a/src/LambdaCube/GL/Backend.hs b/src/LambdaCube/GL/Backend.hs
index c682723..712f357 100644
--- a/src/LambdaCube/GL/Backend.hs
+++ b/src/LambdaCube/GL/Backend.hs
@@ -1,9 +1,9 @@
1{-# LANGUAGE TupleSections, MonadComprehensions, RecordWildCards, LambdaCase #-} 1{-# LANGUAGE TupleSections, MonadComprehensions, RecordWildCards, LambdaCase, FlexibleContexts #-}
2module LambdaCube.GL.Backend where 2module LambdaCube.GL.Backend where
3 3
4import Control.Applicative 4import Control.Applicative
5import Control.Monad 5import Control.Monad
6import Control.Monad.State 6import Control.Monad.State.Strict
7import Data.Maybe 7import Data.Maybe
8import Data.Bits 8import Data.Bits
9import Data.IORef 9import Data.IORef
@@ -497,23 +497,31 @@ allocRenderer p = do
497 -- texture unit mapping ioref trie 497 -- texture unit mapping ioref trie
498 -- texUnitMapRefs :: Map UniformName (IORef TextureUnit) 498 -- texUnitMapRefs :: Map UniformName (IORef TextureUnit)
499 texUnitMapRefs <- Map.fromList <$> mapM (\k -> (k,) <$> newIORef 0) (S.toList $ S.fromList $ concat $ V.toList $ V.map (Map.keys . programInTextures) $ programs p) 499 texUnitMapRefs <- Map.fromList <$> mapM (\k -> (k,) <$> newIORef 0) (S.toList $ S.fromList $ concat $ V.toList $ V.map (Map.keys . programInTextures) $ programs p)
500 let (cmds,st) = runState (mapM (compileCommand texUnitMapRefs smps texs trgs prgs) $ V.toList $ commands p) initCGState 500 let st = execState (mapM_ (compileCommand texUnitMapRefs smps texs trgs prgs) (V.toList $ commands p)) initCGState
501 input <- newIORef Nothing 501 input <- newIORef Nothing
502 -- default Vertex Array Object 502 -- default Vertex Array Object
503 vao <- alloca $! \pvao -> glGenVertexArrays 1 pvao >> peek pvao 503 vao <- alloca $! \pvao -> glGenVertexArrays 1 pvao >> peek pvao
504 strs <- V.mapM compileStreamData $ streams p 504 strs <- V.mapM compileStreamData $ streams p
505 drawContextRef <- newIORef $ error "missing DrawContext"
506 forceSetup <- newIORef True
507 vertexBufferRef <- newIORef 0
508 indexBufferRef <- newIORef 0
505 return $ GLRenderer 509 return $ GLRenderer
506 { glPrograms = prgs 510 { glPrograms = prgs
507 , glTextures = texs 511 , glTextures = texs
508 , glSamplers = smps 512 , glSamplers = smps
509 , glTargets = trgs 513 , glTargets = trgs
510 , glCommands = cmds 514 , glCommands = reverse $ drawCommands st
511 , glSlotPrograms = V.map (V.toList . slotPrograms) $ IR.slots p 515 , glSlotPrograms = V.map (V.toList . slotPrograms) $ IR.slots p
512 , glInput = input 516 , glInput = input
513 , glSlotNames = V.map slotName $ IR.slots p 517 , glSlotNames = V.map slotName $ IR.slots p
514 , glVAO = vao 518 , glVAO = vao
515 , glTexUnitMapping = texUnitMapRefs 519 , glTexUnitMapping = texUnitMapRefs
516 , glStreams = strs 520 , glStreams = strs
521 , glDrawContextRef = drawContextRef
522 , glForceSetup = forceSetup
523 , glVertexBufferRef = vertexBufferRef
524 , glIndexBufferRef = indexBufferRef
517 } 525 }
518 526
519disposeRenderer :: GLRenderer -> IO () 527disposeRenderer :: GLRenderer -> IO ()
@@ -684,20 +692,26 @@ setStorage' p@GLRenderer{..} input' = do
684 buffer binding on various targets: GL_ARRAY_BUFFER, GL_ELEMENT_ARRAY_BUFFER 692 buffer binding on various targets: GL_ARRAY_BUFFER, GL_ELEMENT_ARRAY_BUFFER
685 glEnable/DisableVertexAttribArray 693 glEnable/DisableVertexAttribArray
686-} 694-}
687renderSlot :: [GLObjectCommand] -> IO () 695renderSlot :: IORef GLuint -> IORef GLuint -> [GLObjectCommand] -> IO ()
688renderSlot cmds = forM_ cmds $ \cmd -> do 696renderSlot glVertexBufferRef glIndexBufferRef cmds = forM_ cmds $ \cmd -> do
697 let setup ref v m = do
698 old <- readIORef ref
699 unless (old == v) $ do
700 writeIORef ref v
701 m
702
689 case cmd of 703 case cmd of
690 GLSetVertexAttribArray idx buf size typ ptr -> do 704 GLSetVertexAttribArray idx buf size typ ptr -> do
691 glBindBuffer GL_ARRAY_BUFFER buf 705 setup glVertexBufferRef buf $ glBindBuffer GL_ARRAY_BUFFER buf
692 glEnableVertexAttribArray idx 706 glEnableVertexAttribArray idx
693 glVertexAttribPointer idx size typ (fromIntegral GL_FALSE) 0 ptr 707 glVertexAttribPointer idx size typ (fromIntegral GL_FALSE) 0 ptr
694 GLSetVertexAttribIArray idx buf size typ ptr -> do 708 GLSetVertexAttribIArray idx buf size typ ptr -> do
695 glBindBuffer GL_ARRAY_BUFFER buf 709 setup glVertexBufferRef buf $ glBindBuffer GL_ARRAY_BUFFER buf
696 glEnableVertexAttribArray idx 710 glEnableVertexAttribArray idx
697 glVertexAttribIPointer idx size typ 0 ptr 711 glVertexAttribIPointer idx size typ 0 ptr
698 GLDrawArrays mode first count -> glDrawArrays mode first count 712 GLDrawArrays mode first count -> glDrawArrays mode first count
699 GLDrawElements mode count typ buf indicesPtr -> do 713 GLDrawElements mode count typ buf indicesPtr -> do
700 glBindBuffer GL_ELEMENT_ARRAY_BUFFER buf 714 setup glIndexBufferRef buf $ glBindBuffer GL_ELEMENT_ARRAY_BUFFER buf
701 glDrawElements mode count typ indicesPtr 715 glDrawElements mode count typ indicesPtr
702 GLSetUniform idx (GLUniform ty ref) -> setUniform idx ty ref 716 GLSetUniform idx (GLUniform ty ref) -> setUniform idx ty ref
703 GLBindTexture txTarget tuRef (GLUniform _ ref) -> do 717 GLBindTexture txTarget tuRef (GLUniform _ ref) -> do
@@ -715,105 +729,175 @@ renderSlot cmds = forM_ cmds $ \cmd -> do
715 --isOk <- checkGL 729 --isOk <- checkGL
716 --putStrLn $ isOk ++ " - " ++ show cmd 730 --putStrLn $ isOk ++ " - " ++ show cmd
717 731
732setupRenderTarget glInput GLRenderTarget{..} = do
733 -- set target viewport
734 ic' <- readIORef glInput
735 case ic' of
736 Nothing -> return ()
737 Just ic -> do
738 let input = icInput ic
739 (w,h) <- readIORef $ screenSize input
740 glViewport 0 0 (fromIntegral w) (fromIntegral h)
741 -- TODO: set FBO target viewport
742 glBindFramebuffer GL_DRAW_FRAMEBUFFER framebufferObject
743 case framebufferDrawbuffers of
744 Nothing -> return ()
745 Just bl -> withArray bl $ glDrawBuffers (fromIntegral $ length bl)
746
747setupDrawContext glForceSetup glDrawContextRef glInput new = do
748 old <- readIORef glDrawContextRef
749 writeIORef glDrawContextRef new
750 force <- readIORef glForceSetup
751 writeIORef glForceSetup False
752
753 let setup :: Eq a => (GLDrawContext -> a) -> (a -> IO ()) -> IO ()
754 setup f m = case force of
755 True -> m $ f new
756 False -> do
757 let a = f new
758 unless (a == f old) $ m a
759
760 setup glRenderTarget $ setupRenderTarget glInput
761 setup glRasterContext $ setupRasterContext
762 setup glAccumulationContext setupAccumulationContext
763 setup glProgram glUseProgram
764
765 -- setup texture mapping
766 setup glTextureMapping $ mapM_ $ \(textureUnit,GLTexture{..}) -> do
767 glActiveTexture (GL_TEXTURE0 + fromIntegral textureUnit)
768 glBindTexture glTextureTarget glTextureObject
769
770 -- setup sampler mapping
771 setup glSamplerMapping $ mapM_ $ \(textureUnit,GLSampler{..}) -> do
772 glBindSampler (GL_TEXTURE0 + fromIntegral textureUnit) glSamplerObject
773
774 -- setup sampler uniform mapping
775 setup glSamplerUniformMapping $ mapM_ $ \(textureUnit,GLSamplerUniform{..}) -> do
776 glUniform1i glUniformBinding (fromIntegral textureUnit)
777 writeIORef glUniformBindingRef (fromIntegral textureUnit)
778
718renderFrame :: GLRenderer -> IO () 779renderFrame :: GLRenderer -> IO ()
719renderFrame glp = do 780renderFrame GLRenderer{..} = do
720 glBindVertexArray (glVAO glp) 781 writeIORef glForceSetup True
721 forM_ (glCommands glp) $ \cmd -> do 782 writeIORef glVertexBufferRef 0
783 writeIORef glIndexBufferRef 0
784 glBindVertexArray glVAO
785 forM_ glCommands $ \cmd -> do
722 case cmd of 786 case cmd of
723 GLSetRasterContext rCtx -> setupRasterContext rCtx 787 GLClearRenderTarget rt vals -> do
724 GLSetAccumulationContext aCtx -> setupAccumulationContext aCtx 788 setupRenderTarget glInput rt
725 GLSetRenderTarget rt bufs -> do 789 clearRenderTarget vals
726 -- set target viewport 790 modifyIORef glDrawContextRef $ \ctx -> ctx {glRenderTarget = rt}
727 --when (rt == 0) $ do -- screen out 791
728 ic' <- readIORef $ glInput glp 792 GLRenderStream ctx streamIdx progIdx -> do
729 case ic' of 793 setupDrawContext glForceSetup glDrawContextRef glInput ctx
730 Nothing -> return () 794 drawcmd <- readIORef (glStreamCommands $ glStreams ! streamIdx)
731 Just ic -> do 795 renderSlot glVertexBufferRef glIndexBufferRef drawcmd
732 let input = icInput ic 796
733 (w,h) <- readIORef $ screenSize input 797 GLRenderSlot ctx slotIdx progIdx -> do
734 glViewport 0 0 (fromIntegral w) (fromIntegral h) 798 input <- readIORef glInput
735 -- TODO: set FBO target viewport 799 case input of
736 glBindFramebuffer GL_DRAW_FRAMEBUFFER rt 800 Nothing -> putStrLn "Warning: No pipeline input!" >> return ()
737 case bufs of 801 Just ic -> do
738 Nothing -> return () 802 let draw setupDone obj = readIORef (objEnabled obj) >>= \case
739 Just bl -> withArray bl $ glDrawBuffers (fromIntegral $ length bl) 803 False -> return setupDone
740 GLSetProgram p -> glUseProgram p 804 True -> do
741 GLSetSamplerUniform i tu ref -> glUniform1i i tu >> writeIORef ref tu 805 unless setupDone $ setupDrawContext glForceSetup glDrawContextRef glInput ctx
742 GLSetTexture tu target tx -> glActiveTexture tu >> glBindTexture target tx 806 drawcmd <- readIORef $ objCommands obj
743 GLSetSampler tu s -> glBindSampler tu s 807 --putStrLn "Render object"
744 GLClearRenderTarget vals -> clearRenderTarget vals 808 renderSlot glVertexBufferRef glIndexBufferRef ((drawcmd ! icId ic) ! progIdx)
745 GLGenerateMipMap tu target -> glActiveTexture tu >> glGenerateMipmap target 809 return True
746 GLRenderStream streamIdx progIdx -> do 810 --putStrLn $ "Rendering " ++ show (V.length objs) ++ " objects"
747 renderSlot =<< readIORef (glStreamCommands $ glStreams glp ! streamIdx) 811 readIORef (slotVector (icInput ic) ! (icSlotMapPipelineToInput ic ! slotIdx)) >>= \case
748 GLRenderSlot slotIdx progIdx -> do 812 GLSlot _ objs Ordered -> foldM_ (\a -> draw a . snd) False objs
749 input <- readIORef (glInput glp) 813 GLSlot objMap _ _ -> foldM_ draw False objMap
750 case input of 814
751 Nothing -> putStrLn "Warning: No pipeline input!" >> return ()
752 Just ic -> do
753 let draw obj = do
754 enabled <- readIORef $ objEnabled obj
755 when enabled $ do
756 cmd <- readIORef $ objCommands obj
757 --putStrLn "Render object"
758 renderSlot ((cmd ! icId ic) ! progIdx)
759 --putStrLn $ "Rendering " ++ show (V.length objs) ++ " objects"
760 readIORef (slotVector (icInput ic) ! (icSlotMapPipelineToInput ic ! slotIdx)) >>= \case
761 GLSlot _ objs Ordered -> forM_ objs $ draw . snd
762 GLSlot objMap _ _ -> forM_ objMap draw
763 {-
764 GLSetSampler
765 GLSaveImage
766 GLLoadImage
767 -}
768 --isOk <- checkGL 815 --isOk <- checkGL
769 --putStrLn $ isOk ++ " - " ++ show cmd 816 --putStrLn $ isOk ++ " - " ++ show cmd
770 817
771data CGState 818data CGState
772 = CGState 819 = CGState
773 { currentProgram :: ProgramName 820 { textureBinding :: IntMap GLTexture
774 , textureBinding :: IntMap GLTexture 821 , drawCommands :: [GLCommand]
775 } 822 -- draw context data
823 , rasterContext :: RasterContext
824 , accumulationContext :: AccumulationContext
825 , renderTarget :: GLRenderTarget
826 , currentProgram :: ProgramName
827 , samplerUniformMapping :: [(GLTextureUnit,GLSamplerUniform)]
828 , textureMapping :: [(GLTextureUnit,GLTexture)]
829 , samplerMapping :: [(GLTextureUnit,GLSampler)]
830 }
776 831
777initCGState = CGState 832initCGState = CGState
778 { currentProgram = error "CGState: empty currentProgram" 833 { textureBinding = mempty
779 , textureBinding = IM.empty 834 , drawCommands = mempty
780 } 835 -- draw context data
836 , rasterContext = error "compileCommand: missing RasterContext"
837 , accumulationContext = error "compileCommand: missing AccumulationContext"
838 , renderTarget = error "compileCommand: missing RenderTarget"
839 , currentProgram = error "compileCommand: missing Program"
840 , samplerUniformMapping = mempty
841 , textureMapping = mempty
842 , samplerMapping = mempty
843 }
781 844
782type CG a = State CGState a 845type CG a = State CGState a
783 846
784compileCommand :: Map String (IORef GLint) -> Vector GLSampler -> Vector GLTexture -> Vector GLRenderTarget -> Vector GLProgram -> Command -> CG GLCommand 847emit :: GLCommand -> CG ()
848emit cmd = modify $ \s -> s {drawCommands = cmd : drawCommands s}
849
850drawContext programs =
851 GLDrawContext <$> gets rasterContext
852 <*> gets accumulationContext
853 <*> gets renderTarget
854 <*> gets (programObject . (programs !) . currentProgram)
855 <*> gets textureMapping
856 <*> gets samplerMapping
857 <*> gets samplerUniformMapping
858
859compileCommand :: Map String (IORef GLint) -> Vector GLSampler -> Vector GLTexture -> Vector GLRenderTarget -> Vector GLProgram -> Command -> CG ()
785compileCommand texUnitMap samplers textures targets programs cmd = case cmd of 860compileCommand texUnitMap samplers textures targets programs cmd = case cmd of
786 SetRasterContext rCtx -> return $ GLSetRasterContext rCtx 861 SetRasterContext rCtx -> modify $ \s -> s {rasterContext = rCtx}
787 SetAccumulationContext aCtx -> return $ GLSetAccumulationContext aCtx 862 SetAccumulationContext aCtx -> modify $ \s -> s {accumulationContext = aCtx}
788 SetRenderTarget rt -> let GLRenderTarget fbo bufs = targets ! rt in return $ GLSetRenderTarget fbo bufs 863 SetRenderTarget rt -> modify $ \s -> s {renderTarget = targets ! rt}
789 SetProgram p -> do 864 SetProgram p -> modify $ \s -> s
790 modify (\s -> s {currentProgram = p}) 865 { currentProgram = p
791 return $ GLSetProgram $ programObject $ programs ! p 866 , samplerUniformMapping = mempty
867 , textureMapping = mempty
868 , samplerMapping = mempty
869 }
792 SetSamplerUniform n tu -> do 870 SetSamplerUniform n tu -> do
793 p <- currentProgram <$> get 871 p <- currentProgram <$> get
794 case Map.lookup n (inputTextures $ programs ! p) of 872 case Map.lookup n (inputTextures $ programs ! p) of
795 Nothing -> return (GLSetProgram (programObject $ programs ! p) {-HACK!!! we have to emit something-}) -- TODO: some drivers does heavy cross stage (vertex/fragment) dead code elimination; fail $ "internal error (SetSamplerUniform)! - " ++ show cmd 873 Nothing -> return () -- TODO: some drivers does heavy cross stage (vertex/fragment) dead code elimination; fail $ "internal error (SetSamplerUniform)! - " ++ show cmd
796 Just i -> case Map.lookup n texUnitMap of 874 Just i -> case Map.lookup n texUnitMap of
797 Nothing -> fail $ "internal error (SetSamplerUniform - IORef)! - " ++ show cmd 875 Nothing -> fail $ "internal error (SetSamplerUniform - IORef)! - " ++ show cmd
798 Just r -> return $ GLSetSamplerUniform i (fromIntegral tu) r 876 Just r -> modify $ \s -> s {samplerUniformMapping = (tu, GLSamplerUniform i r) : samplerUniformMapping s}
799 SetTexture tu t -> do 877 SetTexture tu t -> do
800 let tex = textures ! t 878 let tex = textures ! t
801 modify (\s -> s {textureBinding = IM.insert tu tex $ textureBinding s}) 879 modify $ \s -> s
802 return $ GLSetTexture (GL_TEXTURE0 + fromIntegral tu) (glTextureTarget tex) (glTextureObject tex) 880 { textureBinding = IM.insert tu tex $ textureBinding s
803 SetSampler tu s -> return $ GLSetSampler (GL_TEXTURE0 + fromIntegral tu) (maybe 0 (glSamplerObject . (samplers !)) s) 881 , textureMapping = (tu, tex) : textureMapping s
882 }
883 SetSampler tu i -> modify $ \s -> s {samplerMapping = (tu, maybe (GLSampler 0) (samplers !) i) : samplerMapping s}
884
885 -- draw commands
804 RenderSlot slot -> do 886 RenderSlot slot -> do
805 p <- currentProgram <$> get 887 p <- gets currentProgram
806 return $ GLRenderSlot slot p 888 ctx <- drawContext programs
889 emit $ GLRenderSlot ctx slot p
807 RenderStream stream -> do 890 RenderStream stream -> do
808 p <- currentProgram <$> get 891 p <- gets currentProgram
809 return $ GLRenderStream stream p 892 ctx <- drawContext programs
810 ClearRenderTarget vals -> return $ GLClearRenderTarget $ V.toList vals 893 emit $ GLRenderStream ctx stream p
894 ClearRenderTarget vals -> do
895 rt <- gets renderTarget
896 emit $ GLClearRenderTarget rt $ V.toList vals
897{-
811 GenerateMipMap tu -> do 898 GenerateMipMap tu -> do
812 tb <- textureBinding <$> get 899 tb <- textureBinding <$> get
813 case IM.lookup tu tb of 900 case IM.lookup tu tb of
814 Nothing -> fail "internal error (GenerateMipMap)!" 901 Nothing -> fail "internal error (GenerateMipMap)!"
815 Just tex -> return $ GLGenerateMipMap (GL_TEXTURE0 + fromIntegral tu) (glTextureTarget tex) 902 Just tex -> return $ GLGenerateMipMap (GL_TEXTURE0 + fromIntegral tu) (glTextureTarget tex)
816{- 903-} \ No newline at end of file
817 SaveImage _ _ -> undefined
818 LoadImage _ _ -> undefined
819-}
diff --git a/src/LambdaCube/GL/Type.hs b/src/LambdaCube/GL/Type.hs
index 5a9117d..776a425 100644
--- a/src/LambdaCube/GL/Type.hs
+++ b/src/LambdaCube/GL/Type.hs
@@ -128,7 +128,7 @@ data GLTexture
128 = GLTexture 128 = GLTexture
129 { glTextureObject :: GLuint 129 { glTextureObject :: GLuint
130 , glTextureTarget :: GLenum 130 , glTextureTarget :: GLenum
131 } 131 } deriving Eq
132 132
133data InputConnection 133data InputConnection
134 = InputConnection 134 = InputConnection
@@ -159,34 +159,50 @@ data GLRenderer
159 , glVAO :: GLuint 159 , glVAO :: GLuint
160 , glTexUnitMapping :: Map String (IORef GLint) -- maps texture uniforms to texture units 160 , glTexUnitMapping :: Map String (IORef GLint) -- maps texture uniforms to texture units
161 , glStreams :: Vector GLStream 161 , glStreams :: Vector GLStream
162 , glDrawContextRef :: IORef GLDrawContext
163 , glForceSetup :: IORef Bool
164 , glVertexBufferRef :: IORef GLuint
165 , glIndexBufferRef :: IORef GLuint
162 } 166 }
163 167
164data GLSampler 168data GLSampler
165 = GLSampler 169 = GLSampler
166 { glSamplerObject :: GLuint 170 { glSamplerObject :: GLuint
167 } 171 } deriving Eq
168 172
169data GLRenderTarget 173data GLRenderTarget
170 = GLRenderTarget 174 = GLRenderTarget
171 { framebufferObject :: GLuint 175 { framebufferObject :: GLuint
172 , framebufferDrawbuffers :: Maybe [GLenum] 176 , framebufferDrawbuffers :: Maybe [GLenum]
173 } 177 } deriving Eq
178
179type GLTextureUnit = Int
180type GLUniformBinding = GLint
181
182data GLSamplerUniform
183 = GLSamplerUniform
184 { glUniformBinding :: GLUniformBinding
185 , glUniformBindingRef :: IORef GLUniformBinding
186 }
187
188instance Eq GLSamplerUniform where
189 a == b = glUniformBinding a == glUniformBinding b
190
191data GLDrawContext
192 = GLDrawContext
193 { glRasterContext :: RasterContext
194 , glAccumulationContext :: AccumulationContext
195 , glRenderTarget :: GLRenderTarget
196 , glProgram :: GLuint
197 , glTextureMapping :: [(GLTextureUnit,GLTexture)]
198 , glSamplerMapping :: [(GLTextureUnit,GLSampler)]
199 , glSamplerUniformMapping :: [(GLTextureUnit,GLSamplerUniform)]
200 }
174 201
175data GLCommand 202data GLCommand
176 = GLSetRasterContext !RasterContext 203 = GLRenderSlot GLDrawContext SlotName ProgramName
177 | GLSetAccumulationContext !AccumulationContext 204 | GLRenderStream GLDrawContext StreamName ProgramName
178 | GLSetRenderTarget !GLuint !(Maybe [GLenum]) 205 | GLClearRenderTarget GLRenderTarget [ClearImage]
179 | GLSetProgram !GLuint
180 | GLSetSamplerUniform !GLint !GLint (IORef GLint) -- sampler index, texture unit, IORef stores the actual texture unit mapping
181 | GLSetTexture !GLenum !GLuint !GLuint
182 | GLSetSampler !GLuint !GLuint
183 | GLRenderSlot !SlotName !ProgramName
184 | GLRenderStream !StreamName !ProgramName
185 | GLClearRenderTarget [ClearImage]
186 | GLGenerateMipMap !GLenum !GLenum
187 | GLSaveImage FrameBufferComponent ImageRef -- from framebuffer component to texture (image)
188 | GLLoadImage ImageRef FrameBufferComponent -- from texture (image) to framebuffer component
189 deriving Show
190 206
191instance Show (IORef GLint) where 207instance Show (IORef GLint) where
192 show _ = "(IORef GLint)" 208 show _ = "(IORef GLint)"