module Graphics.LambdaCube.RenderSystem.GL.OcclusionQuery where

import Foreign
import Graphics.Rendering.OpenGL.Raw.Core31

import Graphics.LambdaCube.HardwareOcclusionQuery

data GLOcclusionQuery
    = GLOcclusionQuery
    { gloqQueryObject    :: GLuint
    }

instance HardwareOcclusionQuery GLOcclusionQuery where
    beginOcclusionQuery     = glBeginOcclusionQuery
    endOcclusionQuery       = glEndOcclusionQuery
    pullOcclusionQuery      = glPullOcclusionQuery
    isStillOutstanding      = glStillOutstanding

mkGLOcclusionQuery :: IO GLOcclusionQuery
mkGLOcclusionQuery = do
    q <- alloca $ \buf -> glGenQueries 1 buf >> peek buf
    return $ GLOcclusionQuery q

rmGLOcclusionQuery :: GLOcclusionQuery -> IO ()
rmGLOcclusionQuery o = case gloqQueryObject o of
    0 -> return ()
    b -> with b $ \buf -> glDeleteQueries 1 buf

glBeginOcclusionQuery :: GLOcclusionQuery -> IO ()
glBeginOcclusionQuery o = glBeginQuery gl_SAMPLES_PASSED $ gloqQueryObject o

glEndOcclusionQuery :: GLOcclusionQuery -> IO ()
glEndOcclusionQuery _ = glEndQuery gl_SAMPLES_PASSED

glPullOcclusionQuery :: GLOcclusionQuery -> IO Int
glPullOcclusionQuery o = do
    n <- alloca $ \buf -> glGetQueryObjectuiv (gloqQueryObject o) gl_QUERY_RESULT buf >> peek buf
    return $ fromIntegral n

glStillOutstanding :: GLOcclusionQuery -> IO Bool
glStillOutstanding o = do
    b <- alloca $ \buf -> glGetQueryObjectuiv (gloqQueryObject o) gl_QUERY_RESULT_AVAILABLE buf >> peek buf
    return $ b == fromIntegral gl_FALSE