--------------------------------------------------------------------------------
-- |
-- Module      :  Graphics.Rendering.OpenGL.GL.ReadCopyPixels
-- Copyright   :  (c) Sven Panne 2002-2019
-- License     :  BSD3
--
-- Maintainer  :  Sven Panne <svenpanne@gmail.com>
-- Stability   :  stable
-- Portability :  portable
--
-- This module corresponds to section 4.3 (Drawing, Reading, and Copying Pixels)
-- of the OpenGL 2.1 specs.
--
--------------------------------------------------------------------------------

module Graphics.Rendering.OpenGL.GL.ReadCopyPixels (
   -- * Reading Pixels
   readPixels, readBuffer,

   -- * Copying Pixels
   PixelCopyType(..), copyPixels,

   -- * Copying Pixels for framebuffers
   BlitBuffer(..), blitFramebuffer
) where

import Data.StateVar
import Graphics.Rendering.OpenGL.GL.BufferMode
import Graphics.Rendering.OpenGL.GL.CoordTrans
import Graphics.Rendering.OpenGL.GL.PixelData
import Graphics.Rendering.OpenGL.GL.QueryUtils
import Graphics.Rendering.OpenGL.GL.Texturing.Filter
import Graphics.Rendering.OpenGL.GLU.ErrorsInternal
import Graphics.GL

--------------------------------------------------------------------------------

readPixels :: Position -> Size -> PixelData a -> IO ()
readPixels :: Position -> Size -> PixelData a -> IO ()
readPixels (Position x :: GLint
x y :: GLint
y) (Size w :: GLint
w h :: GLint
h) pd :: PixelData a
pd =
   PixelData a -> (GLenum -> GLenum -> Ptr a -> IO ()) -> IO ()
forall a b. PixelData a -> (GLenum -> GLenum -> Ptr a -> b) -> b
withPixelData PixelData a
pd ((GLenum -> GLenum -> Ptr a -> IO ()) -> IO ())
-> (GLenum -> GLenum -> Ptr a -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ GLint
-> GLint -> GLint -> GLint -> GLenum -> GLenum -> Ptr a -> IO ()
forall (m :: * -> *) a.
MonadIO m =>
GLint
-> GLint -> GLint -> GLint -> GLenum -> GLenum -> Ptr a -> m ()
glReadPixels GLint
x GLint
y GLint
w GLint
h

--------------------------------------------------------------------------------

readBuffer :: StateVar BufferMode
readBuffer :: StateVar BufferMode
readBuffer =
   IO BufferMode -> (BufferMode -> IO ()) -> StateVar BufferMode
forall a. IO a -> (a -> IO ()) -> StateVar a
makeStateVar
      ((GLenum -> BufferMode) -> PName1I -> IO BufferMode
forall p a. GetPName1I p => (GLenum -> a) -> p -> IO a
getEnum1 GLenum -> BufferMode
unmarshalBufferMode PName1I
GetReadBuffer)
      (IO () -> (GLenum -> IO ()) -> Maybe GLenum -> IO ()
forall b a. b -> (a -> b) -> Maybe a -> b
maybe IO ()
recordInvalidValue GLenum -> IO ()
forall (m :: * -> *). MonadIO m => GLenum -> m ()
glReadBuffer (Maybe GLenum -> IO ())
-> (BufferMode -> Maybe GLenum) -> BufferMode -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. BufferMode -> Maybe GLenum
marshalBufferMode)

--------------------------------------------------------------------------------

data PixelCopyType =
     CopyColor
   | CopyDepth
   | CopyStencil
   deriving ( PixelCopyType -> PixelCopyType -> Bool
(PixelCopyType -> PixelCopyType -> Bool)
-> (PixelCopyType -> PixelCopyType -> Bool) -> Eq PixelCopyType
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: PixelCopyType -> PixelCopyType -> Bool
$c/= :: PixelCopyType -> PixelCopyType -> Bool
== :: PixelCopyType -> PixelCopyType -> Bool
$c== :: PixelCopyType -> PixelCopyType -> Bool
Eq, Eq PixelCopyType
Eq PixelCopyType =>
(PixelCopyType -> PixelCopyType -> Ordering)
-> (PixelCopyType -> PixelCopyType -> Bool)
-> (PixelCopyType -> PixelCopyType -> Bool)
-> (PixelCopyType -> PixelCopyType -> Bool)
-> (PixelCopyType -> PixelCopyType -> Bool)
-> (PixelCopyType -> PixelCopyType -> PixelCopyType)
-> (PixelCopyType -> PixelCopyType -> PixelCopyType)
-> Ord PixelCopyType
PixelCopyType -> PixelCopyType -> Bool
PixelCopyType -> PixelCopyType -> Ordering
PixelCopyType -> PixelCopyType -> PixelCopyType
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: PixelCopyType -> PixelCopyType -> PixelCopyType
$cmin :: PixelCopyType -> PixelCopyType -> PixelCopyType
max :: PixelCopyType -> PixelCopyType -> PixelCopyType
$cmax :: PixelCopyType -> PixelCopyType -> PixelCopyType
>= :: PixelCopyType -> PixelCopyType -> Bool
$c>= :: PixelCopyType -> PixelCopyType -> Bool
> :: PixelCopyType -> PixelCopyType -> Bool
$c> :: PixelCopyType -> PixelCopyType -> Bool
<= :: PixelCopyType -> PixelCopyType -> Bool
$c<= :: PixelCopyType -> PixelCopyType -> Bool
< :: PixelCopyType -> PixelCopyType -> Bool
$c< :: PixelCopyType -> PixelCopyType -> Bool
compare :: PixelCopyType -> PixelCopyType -> Ordering
$ccompare :: PixelCopyType -> PixelCopyType -> Ordering
$cp1Ord :: Eq PixelCopyType
Ord, Int -> PixelCopyType -> ShowS
[PixelCopyType] -> ShowS
PixelCopyType -> String
(Int -> PixelCopyType -> ShowS)
-> (PixelCopyType -> String)
-> ([PixelCopyType] -> ShowS)
-> Show PixelCopyType
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [PixelCopyType] -> ShowS
$cshowList :: [PixelCopyType] -> ShowS
show :: PixelCopyType -> String
$cshow :: PixelCopyType -> String
showsPrec :: Int -> PixelCopyType -> ShowS
$cshowsPrec :: Int -> PixelCopyType -> ShowS
Show )

marshalPixelCopyType :: PixelCopyType -> GLenum
marshalPixelCopyType :: PixelCopyType -> GLenum
marshalPixelCopyType x :: PixelCopyType
x = case PixelCopyType
x of
   CopyColor -> GLenum
GL_COLOR
   CopyDepth -> GLenum
GL_DEPTH
   CopyStencil -> GLenum
GL_STENCIL

--------------------------------------------------------------------------------

copyPixels :: Position -> Size -> PixelCopyType -> IO ()
copyPixels :: Position -> Size -> PixelCopyType -> IO ()
copyPixels (Position x :: GLint
x y :: GLint
y) (Size w :: GLint
w h :: GLint
h) t :: PixelCopyType
t =
   GLint -> GLint -> GLint -> GLint -> GLenum -> IO ()
forall (m :: * -> *).
MonadIO m =>
GLint -> GLint -> GLint -> GLint -> GLenum -> m ()
glCopyPixels GLint
x GLint
y GLint
w GLint
h (PixelCopyType -> GLenum
marshalPixelCopyType PixelCopyType
t)

--------------------------------------------------------------------------------

-- | The buffers which can be copied with 'blitFramebuffer'.

data BlitBuffer =
     ColorBuffer'
   | StencilBuffer'
   | DepthBuffer'
   deriving ( BlitBuffer -> BlitBuffer -> Bool
(BlitBuffer -> BlitBuffer -> Bool)
-> (BlitBuffer -> BlitBuffer -> Bool) -> Eq BlitBuffer
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: BlitBuffer -> BlitBuffer -> Bool
$c/= :: BlitBuffer -> BlitBuffer -> Bool
== :: BlitBuffer -> BlitBuffer -> Bool
$c== :: BlitBuffer -> BlitBuffer -> Bool
Eq, Eq BlitBuffer
Eq BlitBuffer =>
(BlitBuffer -> BlitBuffer -> Ordering)
-> (BlitBuffer -> BlitBuffer -> Bool)
-> (BlitBuffer -> BlitBuffer -> Bool)
-> (BlitBuffer -> BlitBuffer -> Bool)
-> (BlitBuffer -> BlitBuffer -> Bool)
-> (BlitBuffer -> BlitBuffer -> BlitBuffer)
-> (BlitBuffer -> BlitBuffer -> BlitBuffer)
-> Ord BlitBuffer
BlitBuffer -> BlitBuffer -> Bool
BlitBuffer -> BlitBuffer -> Ordering
BlitBuffer -> BlitBuffer -> BlitBuffer
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: BlitBuffer -> BlitBuffer -> BlitBuffer
$cmin :: BlitBuffer -> BlitBuffer -> BlitBuffer
max :: BlitBuffer -> BlitBuffer -> BlitBuffer
$cmax :: BlitBuffer -> BlitBuffer -> BlitBuffer
>= :: BlitBuffer -> BlitBuffer -> Bool
$c>= :: BlitBuffer -> BlitBuffer -> Bool
> :: BlitBuffer -> BlitBuffer -> Bool
$c> :: BlitBuffer -> BlitBuffer -> Bool
<= :: BlitBuffer -> BlitBuffer -> Bool
$c<= :: BlitBuffer -> BlitBuffer -> Bool
< :: BlitBuffer -> BlitBuffer -> Bool
$c< :: BlitBuffer -> BlitBuffer -> Bool
compare :: BlitBuffer -> BlitBuffer -> Ordering
$ccompare :: BlitBuffer -> BlitBuffer -> Ordering
$cp1Ord :: Eq BlitBuffer
Ord, Int -> BlitBuffer -> ShowS
[BlitBuffer] -> ShowS
BlitBuffer -> String
(Int -> BlitBuffer -> ShowS)
-> (BlitBuffer -> String)
-> ([BlitBuffer] -> ShowS)
-> Show BlitBuffer
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [BlitBuffer] -> ShowS
$cshowList :: [BlitBuffer] -> ShowS
show :: BlitBuffer -> String
$cshow :: BlitBuffer -> String
showsPrec :: Int -> BlitBuffer -> ShowS
$cshowsPrec :: Int -> BlitBuffer -> ShowS
Show )

marshalBlitBuffer :: BlitBuffer -> GLbitfield
marshalBlitBuffer :: BlitBuffer -> GLenum
marshalBlitBuffer x :: BlitBuffer
x = case BlitBuffer
x of
   ColorBuffer' -> GLenum
GL_COLOR_BUFFER_BIT
   StencilBuffer' -> GLenum
GL_STENCIL_BUFFER_BIT
   DepthBuffer' -> GLenum
GL_DEPTH_BUFFER_BIT

--------------------------------------------------------------------------------

blitFramebuffer :: Position
                -> Position
                -> Position
                -> Position
                -> [BlitBuffer]
                -> TextureFilter
                -> IO ()
blitFramebuffer :: Position
-> Position
-> Position
-> Position
-> [BlitBuffer]
-> TextureFilter
-> IO ()
blitFramebuffer (Position sx0 :: GLint
sx0 sy0 :: GLint
sy0)
                (Position sx1 :: GLint
sx1 sy1 :: GLint
sy1)
                (Position dx0 :: GLint
dx0 dy0 :: GLint
dy0)
                (Position dx1 :: GLint
dx1 dy1 :: GLint
dy1)
                buffers :: [BlitBuffer]
buffers
                filt :: TextureFilter
filt =
   GLint
-> GLint
-> GLint
-> GLint
-> GLint
-> GLint
-> GLint
-> GLint
-> GLenum
-> GLenum
-> IO ()
forall (m :: * -> *).
MonadIO m =>
GLint
-> GLint
-> GLint
-> GLint
-> GLint
-> GLint
-> GLint
-> GLint
-> GLenum
-> GLenum
-> m ()
glBlitFramebuffer GLint
sx0 GLint
sy0 GLint
sx1 GLint
sy1 GLint
dx0 GLint
dy0 GLint
dx1 GLint
dy1
                     ([GLenum] -> GLenum
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum ((BlitBuffer -> GLenum) -> [BlitBuffer] -> [GLenum]
forall a b. (a -> b) -> [a] -> [b]
map BlitBuffer -> GLenum
marshalBlitBuffer [BlitBuffer]
buffers))
                     (GLint -> GLenum
forall a b. (Integral a, Num b) => a -> b
fromIntegral (TextureFilter -> GLint
marshalMagnificationFilter TextureFilter
filt))