diff --git a/fsl/fsleyes/gl/__init__.py b/fsl/fsleyes/gl/__init__.py
index 52af7866c80c6afdd26dbd0acc829e1bec028b5d..dffe3c51cb9c945045850fcbb9641f23906871df 100644
--- a/fsl/fsleyes/gl/__init__.py
+++ b/fsl/fsleyes/gl/__init__.py
@@ -187,9 +187,14 @@ package also contains the following:
    ~fsl.fsleyes.gl.shaders
 """
 
-import logging 
+
+import logging
+import platform
 import os
 
+import fsl.utils.async    as async
+import fsl.utils.platform as fslplatform
+
 
 log = logging.getLogger(__name__)
 
@@ -251,6 +256,9 @@ def bootstrap(glVersion=None):
     ``GL_VERSION``         A string containing the target OpenGL version, in 
                            the format ``major.minor``, e.g. ``2.1``.
 
+
+    ``GL_RENDERER``        A string containing the name of the OpenGL renderer.
+
     ``glvolume_funcs``     The version-specific module containing functions for
                            rendering :class:`.GLVolume` instances.
 
@@ -269,6 +277,11 @@ def bootstrap(glVersion=None):
     ``gltensor_funcs``     The version-specific module containing functions for
                            rendering :class:`.GLTensor` instances. 
     ====================== ====================================================
+
+
+    This function also sets the :attr:`.Platform.glVersion` and
+    :attr:`.Platform.glRenderer` properties of the
+    :attr:`fsl.utils.platform.platform` instance.
     
 
     :arg glVersion: A tuple containing the desired (major, minor) OpenGL API
@@ -308,7 +321,6 @@ def bootstrap(glVersion=None):
     # fall back to the gl14 implementation
     if glpkg == gl21:
 
-
         # List any GL21 extensions here
         exts = ['GL_EXT_framebuffer_object',
                 'GL_ARB_instanced_arrays',
@@ -380,6 +392,7 @@ def bootstrap(glVersion=None):
         except ValueError: pass
 
     thismod.GL_VERSION         = verstr
+    thismod.GL_RENDERER        = renderer
     thismod.glvolume_funcs     = glpkg.glvolume_funcs
     thismod.glrgbvector_funcs  = glpkg.glrgbvector_funcs
     thismod.gllinevector_funcs = glpkg.gllinevector_funcs
@@ -387,6 +400,9 @@ def bootstrap(glVersion=None):
     thismod.gllabel_funcs      = glpkg.gllabel_funcs
     thismod.gltensor_funcs     = glpkg.gltensor_funcs
     thismod._bootstrapped      = True
+    
+    fslplatform.glVersion      = thismod.GL_VERSION
+    fslplatform.glRenderer     = thismod.GL_RENDERER
 
 
 def getWXGLContext(parent=None):
@@ -612,6 +628,25 @@ class WXGLCanvasTarget(object):
 
         self._glReady = False
         self.Bind(wx.EVT_PAINT, self._mainDraw)
+
+        # Using the Apple software renderer under OSX,
+        # we need to call refresh on the idle loop,
+        # otherwise refresh of multiple canvases (i.e.
+        # the OrthoPanel). gets all screwed up. Don't
+        # know why.
+        if platform.system() == 'Darwin' and \
+           'software' in fslplatform.glRenderer.lower():
+
+            def refresh(*a):
+                async.idle(self.Refresh)
+
+        # On other platforms/renderers,
+        # we can call Refresh directly
+        else:
+            def refresh(*a):
+                self.Refresh()
+
+        self._refresh = refresh
     
 
     def _initGL(self):
@@ -622,8 +657,12 @@ class WXGLCanvasTarget(object):
 
 
     def _draw(self, *a):
-        """This method should implement the OpenGL drawing logic. Must be
+        """This method should implement the OpenGL drawing logic - it must be
         implemented by subclasses.
+
+        .. note:: When runing with an on-screen display, this method should
+                  never be called directly - call the :meth:`_refresh` method
+                  instead.
         """
         raise NotImplementedError()
  
@@ -670,9 +709,10 @@ class WXGLCanvasTarget(object):
 
         
     def _refresh(self, *a):
-        """Triggers a redraw via the :meth:`_draw` method."""
-        self.Refresh()
+        """Triggers a redraw via the :meth:`_draw` method.
 
+        .. note:: This method is dynamically assigned in :meth:`__init__`.
+        """
         
     def _postDraw(self):
         """Called after the scene has been rendered. Swaps the front/back
diff --git a/fsl/fsleyes/gl/slicecanvas.py b/fsl/fsleyes/gl/slicecanvas.py
index ef31b1c1eb7bac03aa3ac27c27a6853c79b42e1e..bbb27f1f5d1c79a13f0fe3920c800e34372aab93 100644
--- a/fsl/fsleyes/gl/slicecanvas.py
+++ b/fsl/fsleyes/gl/slicecanvas.py
@@ -208,13 +208,13 @@ class SliceCanvas(props.HasProperties):
         # when any of the properties of this
         # canvas change, we need to redraw
         self.addListener('zax',           self.name, self._zAxisChanged)
-        self.addListener('pos',           self.name, self._draw)
-        self.addListener('displayBounds', self.name, self._draw)
-        self.addListener('bgColour',      self.name, self._draw)
-        self.addListener('cursorColour',  self.name, self._draw)
-        self.addListener('showCursor',    self.name, self._draw)
-        self.addListener('invertX',       self.name, self._draw)
-        self.addListener('invertY',       self.name, self._draw)
+        self.addListener('pos',           self.name, self._refresh)
+        self.addListener('displayBounds', self.name, self._refresh)
+        self.addListener('bgColour',      self.name, self._refresh)
+        self.addListener('cursorColour',  self.name, self._refresh)
+        self.addListener('showCursor',    self.name, self._refresh)
+        self.addListener('invertX',       self.name, self._refresh)
+        self.addListener('invertY',       self.name, self._refresh)
         self.addListener('zoom',          self.name, self._zoomChanged)
         self.addListener('renderMode',    self.name, self._renderModeChange)
         self.addListener('resolutionLimit',
diff --git a/fsl/utils/platform.py b/fsl/utils/platform.py
index 844856826a8efe53dc4af83c6056e619cc20f1c0..c3d6ca7a0b687932a464d07533b3612653bc2a4b 100644
--- a/fsl/utils/platform.py
+++ b/fsl/utils/platform.py
@@ -60,12 +60,20 @@ class Platform(notifier.Notifier):
     """The ``Platform`` class contains a handful of properties which contain
     information about the platform we are running on.
 
+    .. note:: The values of the :attr:`glVersion` and :attr:`glRenderer`
+              properties are not automatically set - they will only contain
+              a value if one is assigned to them. The
+              :func:`fsl.fsleyes.gl.bootstrap` function does this when it is
+              first called.
+
     .. autosummary::
 
        fsldir
        haveGui
        wxBuild
        wxFlavour
+       glVersion
+       glRenderer
     """
 
     
@@ -77,6 +85,8 @@ class Platform(notifier.Notifier):
         self.__haveGui    = False
         self.__wxFlavour  = None
         self.__wxPlatform = None
+        self.__glVersion  = None
+        self.__glRenderer = None
 
         try:
             import wx
@@ -151,6 +161,34 @@ class Platform(notifier.Notifier):
         self.__fsldir = value
         self.notify()
 
+        
+    @property
+    def glVersion(self):
+        """Returns the available OpenGL version, or ``None`` if it has not
+        been set.
+        """
+        return self.__glVersion
+
+    
+    @glVersion.setter
+    def glVersion(self, value):
+        """Set the available OpenGL version. """
+        self.__glVersion = value
+
+
+    @property
+    def glRenderer(self):
+        """Returns the available OpenGL renderer, or ``None`` if it has not
+        been set.
+        """
+        return self.__glRenderer
+
+
+    @glRenderer.setter
+    def glRenderer(self, value):
+        """Set the available OpenGL renderer. """
+        self.__glRenderer = value
+
 
 platform = Platform()
 """An instance of the :class:`Platform` class. Feel free to create your own