1313-- entries, providing a portability layer upon platform-specific mechanisms
1414-- like @glXGetProcAddress@, @wglGetProcAddress@ or @NSAddressOfSymbol@.
1515--
16+ -- Note that /finding/ an OpenGL entry point doesn't mean that it's actually
17+ -- /usable:/ On most platforms entry points are context-independent, so you have
18+ -- to check the available extensions and\/or OpenGL version, too.
1619--------------------------------------------------------------------------------
1720
1821module Graphics.Rendering.OpenGL.Raw.GetProcAddress (
@@ -43,7 +46,7 @@ import Foreign.C.String ( CString )
4346import Foreign.C.Types
4447import Foreign.Marshal.Alloc ( alloca )
4548import Foreign.Marshal.Error ( throwIf )
46- import Foreign.Ptr ( Ptr , castPtr , FunPtr , nullFunPtr )
49+ import Foreign.Ptr ( Ptr , nullPtr , castPtr , FunPtr , nullFunPtr )
4750import Foreign.Storable ( peek )
4851import Graphics.Rendering.OpenGL.Raw.Tokens
4952import Graphics.Rendering.OpenGL.Raw.Types
@@ -124,11 +127,10 @@ vendorSuffixes = [
124127getExtensions :: MonadIO m => m (Set String )
125128getExtensions = liftIO $ Data.Set. fromList <$> do
126129 -- glGetStringi is only present from OpenGL 3.0 and OpenGL ES 3.0 onwards, but
127- -- we can not simply retrieve its entry point and check that against
128- -- nullFunPtr: Apart from WGL, entry points are context-independent, so even
129- -- having a entry point which looks valid doesn't guarantee that it is
130- -- actually supported. Therefore we need to check the OpenGL version number
131- -- directly.
130+ -- we can't simply retrieve its entry point and check that against nullFunPtr:
131+ -- Apart from WGL, entry points are context-independent, so even having an
132+ -- entry point which looks valid doesn't guarantee that it is actually
133+ -- supported. Therefore we need to check the OpenGL version number directly.
132134 getString <- makeGetString
133135 v <- getVersionWith getString
134136 if v >= (3 , 0 )
@@ -178,7 +180,7 @@ parseVersion = do
178180makeGetString :: IO (GLenum -> IO String )
179181makeGetString = do
180182 glGetString_ <- dynGLenumIOPtrGLubyte <$> getProcAddress " glGetString"
181- return $ \ name -> glGetString_ name >>= peekUtf8String . castPtr
183+ return $ \ name -> glGetString_ name >>= peekGLstring
182184
183185foreign import CALLCONV " dynamic" dynGLenumIOPtrGLubyte
184186 :: FunPtr (GLenum -> IO (Ptr GLubyte ))
@@ -187,7 +189,7 @@ foreign import CALLCONV "dynamic" dynGLenumIOPtrGLubyte
187189makeGetStringi :: IO (GLenum -> GLuint -> IO String )
188190makeGetStringi = do
189191 glGetStringi_ <- dynGLenumGLuintIOPtrGLubyte <$> getProcAddress " glGetStringi"
190- return $ \ name index -> glGetStringi_ name index >>= peekUtf8String . castPtr
192+ return $ \ name index -> glGetStringi_ name index >>= peekGLstring
191193
192194foreign import CALLCONV " dynamic" dynGLenumGLuintIOPtrGLubyte
193195 :: FunPtr (GLenum -> GLuint -> IO (Ptr GLubyte ))
@@ -204,6 +206,17 @@ foreign import CALLCONV "dynamic" dynGLenumPtrGLintIOVoid
204206
205207--------------------------------------------------------------------------------
206208
209+ -- Play safe, this is in line with OpenGL: Return something, but don't crash.
210+ peekGLstring :: Ptr GLubyte -> IO String
211+ peekGLstring = ptr (return " " ) (peekUtf8String . castPtr)
212+
213+ -- This should really be in Foreign.Ptr.
214+ ptr :: b -> (Ptr a -> b ) -> Ptr a -> b
215+ ptr n f p | p == nullPtr = n
216+ | otherwise = f p
217+
218+ --------------------------------------------------------------------------------
219+
207220withUtf8String :: String -> (CString -> IO a ) -> IO a
208221withUtf8String = unsafeUseAsCString . encodeUtf8 . pack . (++ " \0" )
209222
0 commit comments