diff --git a/ChangeLog.md b/ChangeLog.md
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,3 +1,11 @@
+2.5.3.1
+=======
+
+* Constructors exported for ModalLocation, SurfacePixelFormat, AudioSpec.
+* Added getWindowBordersSize.
+* Added SDL.Input.Mouse.createSystemCursor.
+
+
 2.5.3.0
 =======
 
diff --git a/sdl2.cabal b/sdl2.cabal
--- a/sdl2.cabal
+++ b/sdl2.cabal
@@ -1,5 +1,5 @@
 name:                sdl2
-version:             2.5.3.0
+version:             2.5.3.1
 synopsis:            Both high- and low-level bindings to the SDL library (version 2.0.6+).
 description:
   This package contains bindings to the SDL 2 library, in both high- and
@@ -125,7 +125,7 @@
 
   build-depends:
     base >= 4.7 && < 5,
-    bytestring >= 0.10.4.0 && < 0.11,
+    bytestring >= 0.10.4.0 && < 0.12,
     exceptions >= 0.4 && < 0.11,
     StateVar >= 1.1.0.0 && < 1.3,
     text >= 1.1.0.0 && < 1.3,
diff --git a/src/SDL.hs b/src/SDL.hs
--- a/src/SDL.hs
+++ b/src/SDL.hs
@@ -75,12 +75,18 @@
   renderer <- 'createRenderer' window (-1) 'defaultRenderer'
 @
 
-Finally, we enter our main application loop:
+Then, we enter our main application loop:
 
 @
   appLoop renderer
 @
 
+Finally, once our appLoop has returned we destroy the 'Window' using 'destroyWindow':
+
+@
+  'destroyWindow' window
+@
+
 For the body of your application, we enter a loop. Inside this loop you should begin by collecting all events that
 have happened - these events will inform you about information such as key presses and mouse movement:
 
@@ -134,6 +140,7 @@
   window <- 'createWindow' "My SDL Application" 'defaultWindow'
   renderer <- 'createRenderer' window (-1) 'defaultRenderer'
   appLoop renderer
+  destroyWindow window
 
 appLoop :: 'Renderer' -> IO ()
 appLoop renderer = do
diff --git a/src/SDL/Audio.hs b/src/SDL/Audio.hs
--- a/src/SDL/Audio.hs
+++ b/src/SDL/Audio.hs
@@ -54,13 +54,7 @@
   , getAudioDeviceNames
 
     -- * 'AudioSpec'
-  , AudioSpec
-  , audioSpecFreq
-  , audioSpecFormat
-  , audioSpecChannels
-  , audioSpecSilence
-  , audioSpecSize
-  , audioSpecCallback
+  , AudioSpec(..)
 
     -- * Audio Drivers
   , getAudioDrivers
@@ -175,9 +169,9 @@
         return (audioDevice, spec)
 
   where
-  changes = foldl (.|.) 0 [ foldChangeable (const Raw.SDL_AUDIO_ALLOW_FREQUENCY_CHANGE) (const 0) openDeviceFreq
-                          , foldChangeable (const Raw.SDL_AUDIO_ALLOW_FORMAT_CHANGE) (const 0) openDeviceFormat
-                          , foldChangeable (const Raw.SDL_AUDIO_ALLOW_CHANNELS_CHANGE) (const 0) openDeviceChannels
+  changes = foldl (.|.) 0 [ foldChangeable (const 0) (const Raw.SDL_AUDIO_ALLOW_FREQUENCY_CHANGE) openDeviceFreq
+                          , foldChangeable (const 0) (const Raw.SDL_AUDIO_ALLOW_FORMAT_CHANGE) openDeviceFormat
+                          , foldChangeable (const 0) (const Raw.SDL_AUDIO_ALLOW_CHANNELS_CHANGE) openDeviceChannels
                           ]
 
   channelsToWord8 Mono = 1
diff --git a/src/SDL/Event.hs b/src/SDL/Event.hs
--- a/src/SDL/Event.hs
+++ b/src/SDL/Event.hs
@@ -764,7 +764,7 @@
 --
 -- Like 'pollEvent' this function should only be called in the OS thread which
 -- set the video mode.
-pollEvents :: (Functor m, MonadIO m) => m [Event]
+pollEvents :: MonadIO m => m [Event]
 pollEvents =
   do e <- pollEvent
      case e of
diff --git a/src/SDL/Input/Mouse.hs b/src/SDL/Input/Mouse.hs
--- a/src/SDL/Input/Mouse.hs
+++ b/src/SDL/Input/Mouse.hs
@@ -17,6 +17,7 @@
   , MouseScrollDirection(..)
 
     -- * Mouse State
+  , ModalLocation(..)
   , getModalMouseLocation
   , getAbsoluteMouseLocation
   , getRelativeMouseLocation
@@ -31,10 +32,12 @@
 
     -- * Cursor Shape
   , Cursor
+  , SystemCursor(..)
   , activeCursor
   , createCursor
   , freeCursor
   , createColorCursor
+  , createSystemCursor
   ) where
 
 import Control.Monad (void)
@@ -208,6 +211,35 @@
 newtype Cursor = Cursor { unwrapCursor :: Raw.Cursor }
     deriving (Eq, Typeable)
 
+data SystemCursor
+  = SystemCursorArrow
+  | SystemCursorIBeam
+  | SystemCursorWait
+  | SystemCursorCrossHair
+  | SystemCursorWaitArrow
+  | SystemCursorSizeNWSE
+  | SystemCursorSizeNESW
+  | SystemCursorSizeWE
+  | SystemCursorSizeNS
+  | SystemCursorSizeAll
+  | SystemCursorNo
+  | SystemCursorHand
+
+
+instance ToNumber SystemCursor Word32 where
+  toNumber SystemCursorArrow        = Raw.SDL_SYSTEM_CURSOR_ARROW
+  toNumber SystemCursorIBeam        = Raw.SDL_SYSTEM_CURSOR_IBEAM
+  toNumber SystemCursorWait         = Raw.SDL_SYSTEM_CURSOR_WAIT
+  toNumber SystemCursorCrossHair    = Raw.SDL_SYSTEM_CURSOR_CROSSHAIR
+  toNumber SystemCursorWaitArrow    = Raw.SDL_SYSTEM_CURSOR_WAITARROW
+  toNumber SystemCursorSizeNWSE     = Raw.SDL_SYSTEM_CURSOR_SIZENWSE
+  toNumber SystemCursorSizeNESW     = Raw.SDL_SYSTEM_CURSOR_SIZENESW
+  toNumber SystemCursorSizeWE       = Raw.SDL_SYSTEM_CURSOR_SIZEWE
+  toNumber SystemCursorSizeNS       = Raw.SDL_SYSTEM_CURSOR_SIZENS
+  toNumber SystemCursorSizeAll      = Raw.SDL_SYSTEM_CURSOR_SIZEALL
+  toNumber SystemCursorNo           = Raw.SDL_SYSTEM_CURSOR_NO
+  toNumber SystemCursorHand         = Raw.SDL_SYSTEM_CURSOR_HAND
+
 -- | Get or set the currently active cursor. You can create new 'Cursor's with 'createCursor'.
 --
 -- This 'StateVar' can be modified using '$=' and the current value retrieved with 'get'.
@@ -240,7 +272,8 @@
             V.unsafeWith (V.map (bool 0 1) msk) $ \unsafeMsk ->
                 Raw.createCursor unsafeDta unsafeMsk w h hx hy
 
--- | Free a cursor created with 'createCursor' and 'createColorCusor'.
+
+-- | Free a cursor created with 'createCursor', 'createColorCusor' and 'createSystemCursor'.
 --
 -- See @<https://wiki.libsdl.org/SDL_FreeCursor SDL_FreeCursor>@ for C documentation.
 freeCursor :: MonadIO m => Cursor -> m ()
@@ -257,3 +290,12 @@
     liftIO . fmap Cursor $
         throwIfNull "SDL.Input.Mouse.createColorCursor" "SDL_createColorCursor" $
             Raw.createColorCursor surfPtr hx hy
+
+-- | Create system cursor.
+--
+-- See @<https://wiki.libsdl.org/SDL_CreateSystemCursor SDL_CreateSystemCursor>@ for C documentation.
+createSystemCursor :: MonadIO m => SystemCursor -> m Cursor
+createSystemCursor sc =
+    liftIO . fmap Cursor $
+        throwIfNull "SDL.Input.Mouse.createSystemCursor" "SDL_CreateSystemCursor" $
+            Raw.createSystemCursor (toNumber sc)
diff --git a/src/SDL/Internal/Vect.hs b/src/SDL/Internal/Vect.hs
--- a/src/SDL/Internal/Vect.hs
+++ b/src/SDL/Internal/Vect.hs
@@ -131,7 +131,7 @@
   {-# INLINE (<*>) #-}
 
 instance Monad V2 where
-  return a = V2 a a
+  return = pure
   {-# INLINE return #-}
   V2 a b >>= f = V2 a' b' where
     V2 a' _ = f a
@@ -311,7 +311,7 @@
   {-# INLINE (<*>) #-}
 
 instance Monad V3 where
-  return a = V3 a a a
+  return = pure
   {-# INLINE return #-}
   V3 a b c >>= f = V3 a' b' c' where
     V3 a' _ _ = f a
@@ -504,7 +504,7 @@
   {-# INLINE (<*>) #-}
 
 instance Monad V4 where
-  return a = V4 a a a a
+  return = pure
   {-# INLINE return #-}
   V4 a b c d >>= f = V4 a' b' c' d' where
     V4 a' _ _ _ = f a
diff --git a/src/SDL/Raw/Enum.hsc b/src/SDL/Raw/Enum.hsc
--- a/src/SDL/Raw/Enum.hsc
+++ b/src/SDL/Raw/Enum.hsc
@@ -33,6 +33,27 @@
   pattern SDL_BLENDMODE_ADD,
   pattern SDL_BLENDMODE_MOD,
 
+  -- ** Blend Operation
+  BlendOperation,
+  pattern SDL_BLENDOPERATION_ADD,
+  pattern SDL_BLENDOPERATION_SUBTRACT,
+  pattern SDL_BLENDOPERATION_REV_SUBTRACT,
+  pattern SDL_BLENDOPERATION_MINIMUM,
+  pattern SDL_BLENDOPERATION_MAXIMUM,
+
+  -- ** Blend Factor
+  BlendFactor,
+  pattern SDL_BLENDFACTOR_ZERO,
+  pattern SDL_BLENDFACTOR_ONE,
+  pattern SDL_BLENDFACTOR_SRC_COLOR,
+  pattern SDL_BLENDFACTOR_ONE_MINUS_SRC_COLOR,
+  pattern SDL_BLENDFACTOR_SRC_ALPHA,
+  pattern SDL_BLENDFACTOR_ONE_MINUS_SRC_ALPHA,
+  pattern SDL_BLENDFACTOR_DST_COLOR,
+  pattern SDL_BLENDFACTOR_ONE_MINUS_DST_COLOR,
+  pattern SDL_BLENDFACTOR_DST_ALPHA,
+  pattern SDL_BLENDFACTOR_ONE_MINUS_DST_ALPHA,
+
   -- ** Endian Detetection
   pattern SDL_BYTEORDER,
   pattern SDL_LIL_ENDIAN,
@@ -934,6 +955,8 @@
 type AudioFormat = (#type SDL_AudioFormat)
 type AudioStatus = (#type SDL_AudioStatus)
 type BlendMode = (#type SDL_BlendMode)
+type BlendOperation = (#type SDL_BlendOperation)
+type BlendFactor = (#type SDL_BlendFactor)
 type Endian = CInt
 type EventAction = (#type SDL_eventaction)
 type GameControllerAxis = (#type SDL_GameControllerAxis)
@@ -974,6 +997,23 @@
 pattern SDL_BLENDMODE_BLEND = (#const SDL_BLENDMODE_BLEND) :: BlendMode
 pattern SDL_BLENDMODE_ADD = (#const SDL_BLENDMODE_ADD) :: BlendMode
 pattern SDL_BLENDMODE_MOD = (#const SDL_BLENDMODE_MOD) :: BlendMode
+
+pattern SDL_BLENDOPERATION_ADD = (#const SDL_BLENDOPERATION_ADD) :: BlendOperation
+pattern SDL_BLENDOPERATION_SUBTRACT = (#const SDL_BLENDOPERATION_SUBTRACT) :: BlendOperation
+pattern SDL_BLENDOPERATION_REV_SUBTRACT = (#const SDL_BLENDOPERATION_REV_SUBTRACT) :: BlendOperation
+pattern SDL_BLENDOPERATION_MINIMUM = (#const SDL_BLENDOPERATION_MINIMUM) :: BlendOperation
+pattern SDL_BLENDOPERATION_MAXIMUM = (#const SDL_BLENDOPERATION_MAXIMUM) :: BlendOperation
+
+pattern SDL_BLENDFACTOR_ZERO = (#const SDL_BLENDFACTOR_ZERO) :: BlendFactor
+pattern SDL_BLENDFACTOR_ONE = (#const SDL_BLENDFACTOR_ONE) :: BlendFactor
+pattern SDL_BLENDFACTOR_SRC_COLOR = (#const SDL_BLENDFACTOR_SRC_COLOR) :: BlendFactor
+pattern SDL_BLENDFACTOR_ONE_MINUS_SRC_COLOR = (#const SDL_BLENDFACTOR_ONE_MINUS_SRC_COLOR) :: BlendFactor
+pattern SDL_BLENDFACTOR_SRC_ALPHA = (#const SDL_BLENDFACTOR_SRC_ALPHA) :: BlendFactor
+pattern SDL_BLENDFACTOR_ONE_MINUS_SRC_ALPHA = (#const SDL_BLENDFACTOR_ONE_MINUS_SRC_ALPHA) :: BlendFactor
+pattern SDL_BLENDFACTOR_DST_COLOR = (#const SDL_BLENDFACTOR_DST_COLOR) :: BlendFactor
+pattern SDL_BLENDFACTOR_ONE_MINUS_DST_COLOR = (#const SDL_BLENDFACTOR_ONE_MINUS_DST_COLOR) :: BlendFactor
+pattern SDL_BLENDFACTOR_DST_ALPHA = (#const SDL_BLENDFACTOR_DST_ALPHA) :: BlendFactor
+pattern SDL_BLENDFACTOR_ONE_MINUS_DST_ALPHA = (#const SDL_BLENDFACTOR_ONE_MINUS_DST_ALPHA) :: BlendFactor
 
 pattern SDL_BYTEORDER = (#const SDL_BYTEORDER) :: Endian
 pattern SDL_LIL_ENDIAN = (#const SDL_LIL_ENDIAN) :: Endian
diff --git a/src/SDL/Raw/Types.hsc b/src/SDL/Raw/Types.hsc
--- a/src/SDL/Raw/Types.hsc
+++ b/src/SDL/Raw/Types.hsc
@@ -66,7 +66,9 @@
   Palette(..),
   PixelFormat(..),
   Point(..),
+  FPoint(..),
   Rect(..),
+  FRect(..),
   RendererInfo(..),
   RWops(..),
   Surface(..),
@@ -471,7 +473,7 @@
 
 instance Storable Event where
   sizeOf _ = (#size SDL_Event)
-  alignment = sizeOf
+  alignment _ = 16
   peek ptr = do
     typ <- (#peek SDL_Event, common.type) ptr
     timestamp <- (#peek SDL_Event, common.timestamp) ptr
@@ -1332,6 +1334,22 @@
     (#poke SDL_Point, x) ptr x
     (#poke SDL_Point, y) ptr y
 
+data FPoint = FPoint
+  { fPointX :: !CFloat
+  , fPointY :: !CFloat
+  } deriving (Eq, Show, Typeable)
+
+instance Storable FPoint where
+  sizeOf _ = (#size SDL_FPoint)
+  alignment = sizeOf
+  peek ptr = do
+    x <- (#peek SDL_FPoint, x) ptr
+    y <- (#peek SDL_FPoint, y) ptr
+    return $! FPoint x y
+  poke ptr (FPoint x y) = do
+    (#poke SDL_FPoint, x) ptr x
+    (#poke SDL_FPoint, y) ptr y
+
 data Rect = Rect
   { rectX :: !CInt
   , rectY :: !CInt
@@ -1353,6 +1371,28 @@
     (#poke SDL_Rect, y) ptr y
     (#poke SDL_Rect, w) ptr w
     (#poke SDL_Rect, h) ptr h
+
+data FRect = FRect
+  { fRectX :: !CFloat
+  , fRectY :: !CFloat
+  , fRectW :: !CFloat
+  , fRectH :: !CFloat
+  } deriving (Eq, Show, Typeable)
+
+instance Storable FRect where
+  sizeOf _ = (#size SDL_FRect)
+  alignment = sizeOf
+  peek ptr = do
+    x <- (#peek SDL_FRect, x) ptr
+    y <- (#peek SDL_FRect, y) ptr
+    w <- (#peek SDL_FRect, w) ptr
+    h <- (#peek SDL_FRect, h) ptr
+    return $! FRect x y w h
+  poke ptr (FRect x y w h) = do
+    (#poke SDL_FRect, x) ptr x
+    (#poke SDL_FRect, y) ptr y
+    (#poke SDL_FRect, w) ptr w
+    (#poke SDL_FRect, h) ptr h
 
 data RendererInfo = RendererInfo
   { rendererInfoName :: !CString
diff --git a/src/SDL/Raw/Video.hs b/src/SDL/Raw/Video.hs
--- a/src/SDL/Raw/Video.hs
+++ b/src/SDL/Raw/Video.hs
@@ -32,11 +32,13 @@
   getDisplayDPI,
   getDisplayMode,
   getDisplayName,
+  getDisplayUsableBounds,
   getGrabbedWindow,
   getNumDisplayModes,
   getNumVideoDisplays,
   getNumVideoDrivers,
   getVideoDriver,
+  getWindowBordersSize,
   getWindowBrightness,
   getWindowData,
   getWindowDisplayIndex,
@@ -81,6 +83,7 @@
   videoQuit,
 
   -- * 2D Accelerated Rendering
+  composeCustomBlendMode,
   createRenderer,
   createSoftwareRenderer,
   createTexture,
@@ -103,6 +106,7 @@
   renderClear,
   renderCopy,
   renderCopyEx,
+  renderCopyExF,
   renderDrawLine,
   renderDrawLines,
   renderDrawPoint,
@@ -247,11 +251,13 @@
 foreign import ccall "SDL.h SDL_GetDisplayDPI" getDisplayDPIFFI :: CInt -> Ptr CFloat -> Ptr CFloat -> Ptr CFloat -> IO CInt
 foreign import ccall "SDL.h SDL_GetDisplayMode" getDisplayModeFFI :: CInt -> CInt -> Ptr DisplayMode -> IO CInt
 foreign import ccall "SDL.h SDL_GetDisplayName" getDisplayNameFFI :: CInt -> IO CString
+foreign import ccall "SDL.h SDL_GetDisplayUsableBounds" getDisplayUsableBoundsFFI :: CInt -> Ptr Rect -> IO CInt
 foreign import ccall "SDL.h SDL_GetGrabbedWindow" getGrabbedWindowFFI :: IO Window
 foreign import ccall "SDL.h SDL_GetNumDisplayModes" getNumDisplayModesFFI :: CInt -> IO CInt
 foreign import ccall "SDL.h SDL_GetNumVideoDisplays" getNumVideoDisplaysFFI :: IO CInt
 foreign import ccall "SDL.h SDL_GetNumVideoDrivers" getNumVideoDriversFFI :: IO CInt
 foreign import ccall "SDL.h SDL_GetVideoDriver" getVideoDriverFFI :: CInt -> IO CString
+foreign import ccall "SDL.h SDL_GetWindowBordersSize" getWindowBordersSizeFFI :: Window -> Ptr CInt -> Ptr CInt -> Ptr CInt -> Ptr CInt -> IO CInt
 foreign import ccall "SDL.h SDL_GetWindowBrightness" getWindowBrightnessFFI :: Window -> IO CFloat
 foreign import ccall "SDL.h SDL_GetWindowData" getWindowDataFFI :: Window -> CString -> IO (Ptr ())
 foreign import ccall "SDL.h SDL_GetWindowDisplayIndex" getWindowDisplayIndexFFI :: Window -> IO CInt
@@ -295,6 +301,7 @@
 foreign import ccall "SDL.h SDL_VideoInit" videoInitFFI :: CString -> IO CInt
 foreign import ccall "SDL.h SDL_VideoQuit" videoQuitFFI :: IO ()
 
+foreign import ccall "SDL.h SDL_ComposeCustomBlendMode" composeCustomBlendModeFFI :: BlendFactor -> BlendFactor -> BlendOperation -> BlendFactor -> BlendFactor -> BlendOperation -> IO BlendMode
 foreign import ccall "SDL.h SDL_CreateRenderer" createRendererFFI :: Window -> CInt -> Word32 -> IO Renderer
 foreign import ccall "SDL.h SDL_CreateSoftwareRenderer" createSoftwareRendererFFI :: Ptr Surface -> IO Renderer
 foreign import ccall "SDL.h SDL_CreateTexture" createTextureFFI :: Renderer -> Word32 -> CInt -> CInt -> CInt -> IO Texture
@@ -317,6 +324,7 @@
 foreign import ccall "SDL.h SDL_RenderClear" renderClearFFI :: Renderer -> IO CInt
 foreign import ccall "SDL.h SDL_RenderCopy" renderCopyFFI :: Renderer -> Texture -> Ptr Rect -> Ptr Rect -> IO CInt
 foreign import ccall "SDL.h SDL_RenderCopyEx" renderCopyExFFI :: Renderer -> Texture -> Ptr Rect -> Ptr Rect -> CDouble -> Ptr Point -> RendererFlip -> IO CInt
+foreign import ccall "SDL.h SDL_RenderCopyExF" renderCopyExFFFI :: Renderer -> Texture -> Ptr Rect -> Ptr FRect -> CDouble -> Ptr FPoint -> RendererFlip -> IO CInt
 foreign import ccall "SDL.h SDL_RenderDrawLine" renderDrawLineFFI :: Renderer -> CInt -> CInt -> CInt -> CInt -> IO CInt
 foreign import ccall "SDL.h SDL_RenderDrawLines" renderDrawLinesFFI :: Renderer -> Ptr Point -> CInt -> IO CInt
 foreign import ccall "SDL.h SDL_RenderDrawPoint" renderDrawPointFFI :: Renderer -> CInt -> CInt -> IO CInt
@@ -539,6 +547,10 @@
 getDisplayName v1 = liftIO $ getDisplayNameFFI v1
 {-# INLINE getDisplayName #-}
 
+getDisplayUsableBounds :: MonadIO m => CInt -> Ptr Rect -> m CInt
+getDisplayUsableBounds v1 v2 = liftIO $ getDisplayUsableBoundsFFI v1 v2
+{-# INLINE getDisplayUsableBounds #-}
+
 getGrabbedWindow :: MonadIO m => m Window
 getGrabbedWindow = liftIO getGrabbedWindowFFI
 {-# INLINE getGrabbedWindow #-}
@@ -559,6 +571,10 @@
 getVideoDriver v1 = liftIO $ getVideoDriverFFI v1
 {-# INLINE getVideoDriver #-}
 
+getWindowBordersSize :: MonadIO m => Window -> Ptr CInt -> Ptr CInt -> Ptr CInt -> Ptr CInt -> m CInt
+getWindowBordersSize v1 v2 v3 v4 v5 = liftIO $ getWindowBordersSizeFFI v1 v2 v3 v4 v5
+{-# INLINE getWindowBordersSize #-}
+
 getWindowBrightness :: MonadIO m => Window -> m CFloat
 getWindowBrightness v1 = liftIO $ getWindowBrightnessFFI v1
 {-# INLINE getWindowBrightness #-}
@@ -727,6 +743,10 @@
 videoQuit = liftIO videoQuitFFI
 {-# INLINE videoQuit #-}
 
+composeCustomBlendMode :: MonadIO m => BlendFactor -> BlendFactor -> BlendOperation -> BlendFactor -> BlendFactor -> BlendOperation -> m BlendMode
+composeCustomBlendMode v1 v2 v3 v4 v5 v6 = liftIO $ composeCustomBlendModeFFI v1 v2 v3 v4 v5 v6
+{-# INLINE composeCustomBlendMode #-}
+
 createRenderer :: MonadIO m => Window -> CInt -> Word32 -> m Renderer
 createRenderer v1 v2 v3 = liftIO $ createRendererFFI v1 v2 v3
 {-# INLINE createRenderer #-}
@@ -814,6 +834,10 @@
 renderCopyEx :: MonadIO m => Renderer -> Texture -> Ptr Rect -> Ptr Rect -> CDouble -> Ptr Point -> RendererFlip -> m CInt
 renderCopyEx v1 v2 v3 v4 v5 v6 v7 = liftIO $ renderCopyExFFI v1 v2 v3 v4 v5 v6 v7
 {-# INLINE renderCopyEx #-}
+
+renderCopyExF :: MonadIO m => Renderer -> Texture -> Ptr Rect -> Ptr FRect -> CDouble -> Ptr FPoint -> RendererFlip -> m CInt
+renderCopyExF v1 v2 v3 v4 v5 v6 v7 = liftIO $ renderCopyExFFFI v1 v2 v3 v4 v5 v6 v7
+{-# INLINE renderCopyExF #-}
 
 renderDrawLine :: MonadIO m => Renderer -> CInt -> CInt -> CInt -> CInt -> m CInt
 renderDrawLine v1 v2 v3 v4 v5 = liftIO $ renderDrawLineFFI v1 v2 v3 v4 v5
diff --git a/src/SDL/Video.hs b/src/SDL/Video.hs
--- a/src/SDL/Video.hs
+++ b/src/SDL/Video.hs
@@ -32,6 +32,7 @@
   , windowGrab
   , setWindowMode
   , getWindowAbsolutePosition
+  , getWindowBordersSize
   , setWindowPosition
   , windowTitle
   , windowData
@@ -310,6 +311,21 @@
     alloca $ \hPtr -> do
         Raw.getWindowPosition w wPtr hPtr
         V2 <$> peek wPtr <*> peek hPtr
+
+-- | Get the size of a window's borders (decorations) around the client area (top, left, bottom, right).
+--
+-- See @<https://wiki.libsdl.org/SDL_GetWindowBordersSize SDL_GetWindowBordersSize>@ for C documentation.
+getWindowBordersSize :: MonadIO m => Window -> m (Maybe (V4 CInt))
+getWindowBordersSize (Window win) =
+  liftIO $
+  alloca $ \tPtr ->
+  alloca $ \lPtr ->
+  alloca $ \bPtr ->
+  alloca $ \rPtr -> do
+    n <- Raw.getWindowBordersSize win tPtr lPtr bPtr rPtr
+    if n /= 0
+      then return Nothing
+      else fmap Just $ V4 <$> peek tPtr <*> peek lPtr <*> peek bPtr <*> peek rPtr
 
 -- | Get or set the size of a window's client area. Values beyond the maximum supported size are clamped.
 --
diff --git a/src/SDL/Video/Renderer.hs b/src/SDL/Video/Renderer.hs
--- a/src/SDL/Video/Renderer.hs
+++ b/src/SDL/Video/Renderer.hs
@@ -23,6 +23,7 @@
   , clear
   , copy
   , copyEx
+  , copyExF
   , drawLine
   , drawLines
   , drawPoint
@@ -78,7 +79,7 @@
   , paletteColors
   , paletteColor
   , PixelFormat(..)
-  , SurfacePixelFormat
+  , SurfacePixelFormat(..)
   , formatPalette
   , setPaletteColors
   , pixelFormatToMasks
@@ -764,6 +765,27 @@
                       V2 x y -> (if x then Raw.SDL_FLIP_HORIZONTAL else 0) .|.
                                (if y then Raw.SDL_FLIP_VERTICAL else 0))
 
+-- | Copy a portion of the texture to the current rendering target, optionally rotating it by angle around the given center and also flipping it top-bottom and/or left-right.
+copyExF :: MonadIO m
+       => Renderer -- ^ The rendering context
+       -> Texture -- ^ The source texture
+       -> Maybe (Rectangle CInt) -- ^ The source rectangle to copy, or 'Nothing' for the whole texture
+       -> Maybe (Rectangle CFloat) -- ^ The destination rectangle to copy to, or 'Nothing' for the whole rendering target. The texture will be stretched to fill the given rectangle.
+       -> CDouble -- ^ The angle of rotation in degrees. The rotation will be performed clockwise.
+       -> Maybe (Point V2 CFloat) -- ^ The point indicating the center of the rotation, or 'Nothing' to rotate around the center of the destination rectangle
+       -> V2 Bool -- ^ Whether to flip the texture on the X and/or Y axis
+       -> m ()
+copyExF (Renderer r) (Texture t) srcRect dstRect theta center flips =
+  liftIO $
+  throwIfNeg_ "SDL.Video.copyExF" "SDL_RenderCopyExF" $
+  maybeWith with srcRect $ \src ->
+  maybeWith with dstRect $ \dst ->
+  maybeWith with center $ \c ->
+  Raw.renderCopyExF r t (castPtr src) (castPtr dst) theta (castPtr c)
+                   (case flips of
+                      V2 x y -> (if x then Raw.SDL_FLIP_HORIZONTAL else 0) .|.
+                               (if y then Raw.SDL_FLIP_VERTICAL else 0))
+
 -- | Draw a line on the current rendering target.
 --
 -- See @<https://wiki.libsdl.org/SDL_RenderDrawLine SDL_RenderDrawLine>@ for C documentation.
@@ -903,7 +925,7 @@
     Raw.setTextureColorMod t r g b
 
 data PixelFormat
-  = Unknown
+  = Unknown !Word32
   | Index1LSB
   | Index1MSB
   | Index4LSB
@@ -939,11 +961,10 @@
   | YUY2
   | UYVY
   | YVYU
-  deriving (Bounded, Data, Enum, Eq, Generic, Ord, Read, Show, Typeable)
+  deriving (Data, Eq, Generic, Ord, Read, Show, Typeable)
 
 instance FromNumber PixelFormat Word32 where
   fromNumber n' = case n' of
-    Raw.SDL_PIXELFORMAT_UNKNOWN -> Unknown
     Raw.SDL_PIXELFORMAT_INDEX1LSB -> Index1LSB
     Raw.SDL_PIXELFORMAT_INDEX1MSB -> Index1MSB
     Raw.SDL_PIXELFORMAT_INDEX4LSB -> Index4LSB
@@ -979,11 +1000,12 @@
     Raw.SDL_PIXELFORMAT_YUY2 -> YUY2
     Raw.SDL_PIXELFORMAT_UYVY -> UYVY
     Raw.SDL_PIXELFORMAT_YVYU -> YVYU
-    _ -> error "fromNumber: not numbered"
+    Raw.SDL_PIXELFORMAT_UNKNOWN -> Unknown n'
+    _ -> Unknown n'
 
 instance ToNumber PixelFormat Word32 where
   toNumber pf = case pf of
-    Unknown -> Raw.SDL_PIXELFORMAT_UNKNOWN
+    Unknown _ -> Raw.SDL_PIXELFORMAT_UNKNOWN
     Index1LSB -> Raw.SDL_PIXELFORMAT_INDEX1LSB
     Index1MSB -> Raw.SDL_PIXELFORMAT_INDEX1MSB
     Index4LSB -> Raw.SDL_PIXELFORMAT_INDEX4LSB
