packages feed

GPipe-GLFW 1.4.0 → 1.4.1

raw patch · 9 files changed

+133/−71 lines, 9 filesPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

API changes (from Hackage documentation)

- Graphics.GPipe.Context.GLFW.Wrapped: windowShouldClose :: MonadIO m => Window os c ds -> ContextT Handle os m (Maybe Bool)
+ Graphics.GPipe.Context.GLFW.Misc: Error'ApiUnavailable :: Error
+ Graphics.GPipe.Context.GLFW.Misc: Error'FormatUnavailable :: Error
+ Graphics.GPipe.Context.GLFW.Misc: Error'InvalidEnum :: Error
+ Graphics.GPipe.Context.GLFW.Misc: Error'InvalidValue :: Error
+ Graphics.GPipe.Context.GLFW.Misc: Error'NoCurrentContext :: Error
+ Graphics.GPipe.Context.GLFW.Misc: Error'NotInitialized :: Error
+ Graphics.GPipe.Context.GLFW.Misc: Error'OutOfMemory :: Error
+ Graphics.GPipe.Context.GLFW.Misc: Error'PlatformError :: Error
+ Graphics.GPipe.Context.GLFW.Misc: Error'VersionUnavailable :: Error
+ Graphics.GPipe.Context.GLFW.Misc: data Error :: *
+ Graphics.GPipe.Context.GLFW.Window: setWindowCloseCallback :: MonadIO m => Window os c ds -> Maybe (IO ()) -> ContextT Handle os m (Maybe ())
+ Graphics.GPipe.Context.GLFW.Window: setWindowShouldClose :: MonadIO m => Window os c ds -> Bool -> ContextT Handle os m (Maybe ())
+ Graphics.GPipe.Context.GLFW.Window: windowShouldClose :: MonadIO m => Window os c ds -> ContextT Handle os m (Maybe Bool)

Files

GPipe-GLFW.cabal view
@@ -1,5 +1,5 @@ name:           GPipe-GLFW-version:        1.4.0+version:        1.4.1 cabal-version:  >=1.10 build-type:     Simple author:         Patrick Redmond@@ -29,7 +29,8 @@   default-language:    Haskell2010   exposed-modules:     Graphics.GPipe.Context.GLFW                        Graphics.GPipe.Context.GLFW.Input-                       Graphics.GPipe.Context.GLFW.Wrapped+                       Graphics.GPipe.Context.GLFW.Window+                       Graphics.GPipe.Context.GLFW.Misc   other-modules:       Graphics.GPipe.Context.GLFW.Calls                        Graphics.GPipe.Context.GLFW.Resource                        Graphics.GPipe.Context.GLFW.Wrappers@@ -46,4 +47,4 @@   type:     git   location: https://github.com/plredmond/GPipe-GLFW.git   subdir:   GPipe-GLFW-  tag:      v1.4.0+  tag:      v1.4.1
src/Graphics/GPipe/Context/GLFW.hs view
@@ -1,24 +1,22 @@ -- | Non interactive applications only need to pass configuration defined here -- into GPipe's 'runContextT' and 'newWindow'. ----- For user input, see "Graphics.GPipe.Context.GLFW.Input". All other GLFW--- functionality is being incrementally exposed in--- "Graphics.GPipe.Context.GLFW.Wrapped".+-- Interactive applications will need "Graphics.GPipe.Context.GLFW.Input". module Graphics.GPipe.Context.GLFW ( -- * GPipe context handler for GLFW Handle(), GLFWWindow(), -- ** Configuration--- *** Defaults+-- *** Default configs defaultHandleConfig, defaultWindowConfig,--- *** Details+-- *** Custom configs ContextHandlerParameters(HandleConfig, configErrorCallback, configEventPolicy), -- | Configuration for the GLFW handle. -- -- [@'HandleConfig'@] Constructor ----- [@'configErrorCallback' :: ErrorCallback@] Specify a callback to handle errors captured by GLFW.+-- [@'configErrorCallback' ::  'Error' -> String -> IO () @] Specify a callback to handle errors emitted by GLFW. -- -- [@'configEventPolicy' :: Maybe 'EventPolicy'@] Specify the 'EventPolicy' to use for automatic GLFW event processing. If 'Nothing' then automatic event processing is disabled and you'll need to call 'mainloop' or 'mainstep' somewhere. WindowConfig(..),@@ -32,7 +30,8 @@ mainstep, -- ** Reexports module Graphics.GPipe.Context.GLFW.Input,-module Graphics.GPipe.Context.GLFW.Wrapped+module Graphics.GPipe.Context.GLFW.Window,+module Graphics.GPipe.Context.GLFW.Misc ) where  -- internal@@ -41,4 +40,5 @@ import Graphics.GPipe.Context.GLFW.Handler -- reexports import Graphics.GPipe.Context.GLFW.Input-import Graphics.GPipe.Context.GLFW.Wrapped+import Graphics.GPipe.Context.GLFW.Window+import Graphics.GPipe.Context.GLFW.Misc
src/Graphics/GPipe/Context/GLFW/Calls.hs view
@@ -14,13 +14,18 @@ -- TODO: maybe an OnMain monad would be good to reduce the number of RPCS? Not really necessary, since they can already be easily sequenced with IO  -- |+-- * This function may be called from any thread.+getCurrentContext :: IO (Maybe GLFW.Window)+getCurrentContext = GLFW.getCurrentContext++-- | -- * 2x This function may be called from any thread. -- * Reading and writing of the internal timer offset is not atomic, so it needs to be externally synchronized with calls to glfwSetTime. debug :: String -> IO () debug msg = do     t <- GLFW.getTime     tid <- Conc.myThreadId-    c <- GLFW.getCurrentContext+    c <- getCurrentContext     Text.printf "[%03.3fs, %s has %s]: %s\n" (maybe (0/0) id t) (show tid) (show c) msg  type OnMain a = IO a -> IO a@@ -75,7 +80,7 @@ -- * This function may be called from any thread. makeContextCurrent :: String -> Maybe GLFW.Window -> IO () makeContextCurrent reason windowHuh = do-    ccHuh <- GLFW.getCurrentContext+    ccHuh <- getCurrentContext     when (ccHuh /= windowHuh) $ do         debug $ Text.printf "attaching %s, reason: %s" (show windowHuh) reason         GLFW.makeContextCurrent windowHuh@@ -119,6 +124,11 @@ -- * This function may be called from any thread. Access is not synchronized. setWindowShouldClose :: GLFW.Window -> Bool -> IO () setWindowShouldClose window bool = GLFW.setWindowShouldClose window bool++-- |+-- * This function must only be called from the main thread.+setWindowCloseCallback :: EffectMain -> GLFW.Window -> Maybe GLFW.WindowCloseCallback -> IO ()+setWindowCloseCallback onMain window cb = onMain $ GLFW.setWindowCloseCallback window cb  -- | -- * This function must only be called from the main thread.
src/Graphics/GPipe/Context/GLFW/Format.hs view
@@ -21,8 +21,8 @@ instance Exception [WindowHint]  allowedHint :: WindowHint -> Bool-allowedHint (WindowHint'sRGBCapable _) = False allowedHint (WindowHint'Visible _) = False+allowedHint (WindowHint'sRGBCapable _) = False allowedHint (WindowHint'RedBits _) = False allowedHint (WindowHint'GreenBits _) = False allowedHint (WindowHint'BlueBits _) = False
src/Graphics/GPipe/Context/GLFW/Handler.hs view
@@ -23,8 +23,8 @@     , ThreadId, myThreadId     ) -- thirdparty-import qualified Graphics.GPipe.Context as GPipe (ContextHandler(..), Window(), ContextT(), withContextWindow)-import qualified Graphics.UI.GLFW as GLFW (Window, ErrorCallback)+import qualified Graphics.GPipe as GPipe (ContextHandler(..), Window(), ContextT(), WindowBits, withContextWindow)+import qualified Graphics.UI.GLFW as GLFW (Window, Error) -- local import qualified Graphics.GPipe.Context.GLFW.Calls as Call import qualified Graphics.GPipe.Context.GLFW.Format as Format@@ -59,6 +59,7 @@ data Handle = Handle     { handleTid :: ThreadId     , handleComm :: RPC.Handle+    , handleRaw :: GLFW.Window     , handleCtxs :: TVar [MMContext]     , handleEventPolicy :: Maybe EventPolicy     }@@ -74,14 +75,6 @@         go Nothing = Call.debug (printf "%s: GPipe-GLFW context already closed" callerTag) >> return Nothing         go (Just context) = pure <$> action context --- FIXME: May cause crashes in windows (os) because windows (os) requires parent contexts to be uncurrent; easy fix--- | Run the action. If any open context is avaiable, take it and pass it into the action.-withAnyContext :: Handle -> (Maybe Context -> IO a) -> IO a-withAnyContext handle action = readTVarIO (handleCtxs handle) >>= go-    where-        go (mmContext:ctxs) = withContext "withAnyContext" mmContext (action . pure) >>= maybe (go ctxs) return-        go [] = action Nothing- -- | Template for "Run the action with XYZ /if the gpipe window still exists and ABC/." unwrappingGPipeWindow :: MonadIO m     => (String -> action -> Handle -> MMContext -> IO (Maybe a)) -- ^ Specialize use of unwrappingGPipeWindow@@ -127,8 +120,8 @@      -- | Configuration for the GLFW handle.     data ContextHandlerParameters Handle = HandleConfig-        { -- | Specify a callback to handle errors captured by GLFW.-          configErrorCallback :: GLFW.ErrorCallback+        { -- | Specify a callback to handle errors emitted by GLFW.+          configErrorCallback :: GLFW.Error -> String -> IO ()           -- | Specify the 'EventPolicy' to use for automatic GLFW event           -- processing. Set to 'Nothing' to disable automatic event processing           -- (you'll need to call 'mainloop' or 'mainstep').@@ -143,30 +136,10 @@     -- Create a context which shares objects with the contexts created by this     -- handle, if any.     createContext handle settings = do-        unless (null disallowedHints) $-            throwIO $ Format.UnsafeWindowHintsException disallowedHints-        -- make a context-        window <- withAnyContext handle $ \parent -> do-            windowHuh <- Call.createWindow (onMain handle) width height title monitor hints (contextRaw <$> parent)-            Call.debug $ printf "contextCreate made %s -> parent %s" (show windowHuh) (show $ contextRaw <$> parent)-            case (windowHuh, parent) of-                (Just w, _) -> return w-                (Nothing, Just _) -> throwIO . CreateSharedWindowException . show $ config {Resource.configHints = hints}-                (Nothing, Nothing) -> throwIO . CreateWindowException . show $ config {Resource.configHints = hints}-        -- set up context-        forM_ intervalHuh $ \interval -> do-            Call.makeContextCurrent "apply vsync setting" $ pure window-            Call.swapInterval interval-        -- wrap up context+        window <- createWindow (Just $ handleRaw handle) settings         mmContext <- newMVar . pure $ Context window         atomically $ modifyTVar (handleCtxs handle) (mmContext :)         return $ WWindow (mmContext, handle)-        where-            config = fromMaybe (defaultWindowConfig "") (snd <$> settings)-            Resource.WindowConfig {Resource.configWidth=width, Resource.configHeight=height} = config-            Resource.WindowConfig _ _ title monitor _ intervalHuh = config-            (userHints, disallowedHints) = partition Format.allowedHint $ Resource.configHints config-            hints = userHints ++ Format.bitsToHints (fst <$> settings) ++ Format.unconditionalHints      -- Threading assumption: any thread     --@@ -175,11 +148,17 @@     --     -- XXX: If there's a lot of context swapping, change this to RPC to a     -- context-private thread running a mainloop.-    contextDoAsync _ Nothing _action = do-        Call.debug "TODO: contextDoAsync called w/o context; ensure any context is current"+    contextDoAsync handle Nothing action = RPC.sendEffect (handleComm handle) $ do+        -- (on main thread) Make the ancestor current if nothing else already is+        -- FIXME: these two bodies could be combined, perhaps.. the RPC is only necessary if the current thread lacks a context+        ccHuh <- Call.getCurrentContext+        maybe (Call.makeContextCurrent "contextDoAsync required some context" . pure . handleRaw $ handle)+            (const $ return ())+            ccHuh+        action     contextDoAsync _ (Just (WWindow (mmContext, _))) action =         void $ withContext "contextDoAsync" mmContext $ \context -> do-            Call.makeContextCurrent "contextDoAsync required it" . pure . contextRaw $ context+            Call.makeContextCurrent "contextDoAsync required a specific context" . pure . contextRaw $ context             action      -- Threading assumption: main thread@@ -231,7 +210,8 @@         ok <- Call.init id -- id RPC because contextHandlerCreate is called only on mainthread         unless ok $ throwIO InitException         -- wrap up handle-        return $ Handle tid comm ctxs eventPolicy+        ancestor <- createWindow Nothing Nothing+        return $ Handle tid comm ancestor ctxs eventPolicy         where             HandleConfig errorHandler eventPolicy = config @@ -244,6 +224,29 @@         -- all resources are released         Call.terminate id -- id RPC because contextHandlerDelete is called only on mainthread         Call.setErrorCallback id Nothing -- id RPC because contextHandlerDelete is called only on mainthread++-- Create a raw GLFW window for use by contextHandlerCreate & createContext+createWindow :: Maybe GLFW.Window -> Maybe (GPipe.WindowBits, Resource.WindowConfig) -> IO GLFW.Window+createWindow parentHuh settings = do+    unless (null disallowedHints) $+        throwIO $ Format.UnsafeWindowHintsException disallowedHints+    -- make a context+    windowHuh <- Call.createWindow id width height title monitor hints parentHuh -- id RPC because contextHandlerCreate & createContext are called only on mainthread+    Call.debug $ printf "made context %s -> parent %s" (show windowHuh) (show parentHuh)+    window <- maybe exc return windowHuh+    -- set up context+    forM_ intervalHuh $ \interval -> do+        Call.makeContextCurrent "apply vsync setting" $ pure window+        Call.swapInterval interval+    -- done+    return window+    where+        config = fromMaybe (defaultWindowConfig "") (snd <$> settings)+        Resource.WindowConfig {Resource.configWidth=width, Resource.configHeight=height} = config+        Resource.WindowConfig _ _ title monitor _ intervalHuh = config+        (userHints, disallowedHints) = partition Format.allowedHint $ Resource.configHints config+        hints = userHints ++ Format.bitsToHints (fst <$> settings) ++ Format.unconditionalHints+        exc = throwIO . CreateSharedWindowException . show $ config {Resource.configHints = hints}  -- | Type to describe the waiting or polling style of event processing -- supported by GLFW.
src/Graphics/GPipe/Context/GLFW/Input.hs view
@@ -1,6 +1,5 @@ -- | User input functions covering much of the GLFW __Input guide__: -- <http://www.glfw.org/docs/latest/input_guide.html>.--- For additional functionality see "Graphics.GPipe.Context.GLFW.Wrapped". -- -- Actions are in the GPipe 'GPipe.ContextT' monad when a window handle is required, -- otherwise they are bare reexported IO actions which can be lifted into the 'GPipe.ContextT' monad.
+ src/Graphics/GPipe/Context/GLFW/Misc.hs view
@@ -0,0 +1,15 @@+-- | Miscellaneous wrapped calls to GLFW-b for application programmer use.+--+-- Actions are in the GPipe 'GPipe.ContextT' monad when a window handle is required,+-- otherwise they are bare reexported IO actions which can be lifted into the 'GPipe.ContextT' monad.+-- The 'Window' taken by many of these functions is the window resource from GPipe.+module Graphics.GPipe.Context.GLFW.Misc (+-- * Error handling+-- | Learn more: http://www.glfw.org/docs/latest/intro_guide.html#error_handling++-- | To set a custom error callback use 'HandleConfig' in "Graphics.GPipe.Context.GLFW".+Error(..),+) where++-- thirdparty+import Graphics.UI.GLFW (Error(..))
+ src/Graphics/GPipe/Context/GLFW/Window.hs view
@@ -0,0 +1,53 @@+-- | Window manipulation functions covering much of the GLFW __Window guide__:+-- <http://www.glfw.org/docs/latest/window_guide.html>.+-- Notably absent are the window creation functions. These are handled automatically by GPipe-GLFW.+--+-- Actions are in the GPipe 'GPipe.ContextT' monad when a window handle is required,+-- otherwise they are bare reexported IO actions which can be lifted into the 'GPipe.ContextT' monad.+-- The 'Window' taken by many of these functions is the window resource from GPipe.++module Graphics.GPipe.Context.GLFW.Window (+-- * Window objects+-- | Learn more: http://www.glfw.org/docs/latest/window_guide.html#window_object++-- * Window event processing+-- | GLFW event processing is performed by 'GPipe-GLFW' after each call to the 'GPipe' @swapBuffers@.+-- No further action is required, but additional controls are available for complex applications in+-- "Graphics.GPipe.Context.GLFW".++-- * Window properties and events+-- | Learn more: http://www.glfw.org/docs/latest/window_guide.html#window_properties++-- ** Window closing and close flag+windowShouldClose,+setWindowShouldClose,+setWindowCloseCallback,++-- * Buffer swapping+-- | Buffer swapping is initiated via the 'GPipe' @swapBuffers@ function.++-- * Not supported+-- | Some GLFW functionality isn't currently exposed by "Graphics.UI.GLFW".+--+--      * `glfwSetWindowUserPointer`, `glfwGetWindowUserPointer`+) where++-- stdlib+import Control.Monad.IO.Class (MonadIO)+--thirdparty+import qualified Graphics.GPipe.Context as GPipe (ContextT, Window())+--local+import Graphics.GPipe.Context.GLFW.Handler (Handle(..))+import qualified Graphics.GPipe.Context.GLFW.Calls as Call+import qualified Graphics.GPipe.Context.GLFW.Wrappers as Wrappers++-- TODO: function docstrings++windowShouldClose :: MonadIO m => GPipe.Window os c ds -> GPipe.ContextT Handle os m (Maybe Bool)+windowShouldClose = Wrappers.withWindow Call.windowShouldClose++setWindowShouldClose :: MonadIO m => GPipe.Window os c ds -> Bool -> GPipe.ContextT Handle os m (Maybe ())+setWindowShouldClose w b = Wrappers.withWindow (flip Call.setWindowShouldClose b) w++setWindowCloseCallback :: MonadIO m => GPipe.Window os c ds -> Maybe (IO ()) -> GPipe.ContextT Handle os m (Maybe ())+setWindowCloseCallback = Wrappers.wrapCallbackSetter Call.setWindowCloseCallback
− src/Graphics/GPipe/Context/GLFW/Wrapped.hs
@@ -1,19 +0,0 @@--- | Wrapped calls to GLFW-b for application programmer use. For user input see--- "Graphics.GPipe.Context.GLFW.Input".------ Actions are in the GPipe 'GPipe.ContextT' monad when a window handle is required,--- otherwise they are bare reexported IO actions which can be lifted into the 'GPipe.ContextT' monad.--- The 'Window' taken by many of these functions is the window resource from GPipe.-module Graphics.GPipe.Context.GLFW.Wrapped where---- stdlib-import Control.Monad.IO.Class (MonadIO)--- thirdparty-import qualified Graphics.GPipe.Context as GPipe (ContextT, Window())--- local-import Graphics.GPipe.Context.GLFW.Handler (Handle(..))-import qualified Graphics.GPipe.Context.GLFW.Calls as Call-import qualified Graphics.GPipe.Context.GLFW.Wrappers as Wrappers--windowShouldClose :: MonadIO m => GPipe.Window os c ds -> GPipe.ContextT Handle os m (Maybe Bool)-windowShouldClose = Wrappers.withWindow Call.windowShouldClose