diff --git a/fsl/fsleyes/gl/lightboxcanvas.py b/fsl/fsleyes/gl/lightboxcanvas.py
index fa193d337dabc89b278839ff5f5d08bc3ade4d52..3a6a62721d5a998b8844593d2e2aeba7a0ba8ff9 100644
--- a/fsl/fsleyes/gl/lightboxcanvas.py
+++ b/fsl/fsleyes/gl/lightboxcanvas.py
@@ -317,23 +317,11 @@ class LightBoxCanvas(slicecanvas.SliceCanvas):
                     continue
 
                 globj = self._glObjects.get(overlay, None)
-                
+
                 if globj is None:
                     continue
                 
-                name = '{}_{}_zax{}'.format(
-                    id(overlay),
-                    textures.RenderTextureStack.__name__,
-                    self.zax)
-
-                if glresources.exists(name):
-                    rt = glresources.get(name)
-                else:
-
-                    rt = textures.RenderTextureStack(globj)
-                    rt.setAxes(self.xax, self.yax)
-                    glresources.set(name, rt)
-
+                rt, name = self._getPreRenderTexture(globj, overlay)
                 self._prerenderTextures[overlay] = rt, name
 
         self._refresh()
diff --git a/fsl/fsleyes/gl/slicecanvas.py b/fsl/fsleyes/gl/slicecanvas.py
index b91587a471ca5fd194535d5d58c61d981fe5f355..6d062a8ef4eb4fa582826bf814a219d2ae596a47 100644
--- a/fsl/fsleyes/gl/slicecanvas.py
+++ b/fsl/fsleyes/gl/slicecanvas.py
@@ -227,6 +227,9 @@ class SliceCanvas(props.HasProperties):
         self.displayCtx .addListener('bounds',
                                      self.name,
                                      self._overlayBoundsChanged)
+        self.displayCtx .addListener('syncOverlayDisplay',
+                                     self.name,
+                                     self._syncOverlayDisplayChanged) 
 
 
     def destroy(self):
@@ -480,23 +483,53 @@ class SliceCanvas(props.HasProperties):
             # is managed by a RenderTextureStack
             # object.
             elif self.renderMode == 'prerender':
-                name = '{}_{}_zax{}'.format(
-                    id(overlay),
-                    textures.RenderTextureStack.__name__,
-                    self.zax)
-
-                if glresources.exists(name):
-                    rt = glresources.get(name)
-                    
-                else:
-                    rt = textures.RenderTextureStack(globj)
-                    rt.setAxes(self.xax, self.yax)
-                    glresources.set(name, rt)
-
+                rt, name = self._getPreRenderTexture(globj, overlay)
                 self._prerenderTextures[overlay] = rt, name
 
         self._refresh()
 
+        
+    def _getPreRenderTexture(self, globj, overlay):
+        """Creates/retrieves a :class:`.RenderTextureStack` for the given
+        :class:`.GLObject`. A tuple containing the ``RenderTextureStack``,
+        and its name, as passed to the :mod:`.resources` module, is returned.
+
+        :arg globj:   The :class:`.GLObject` instance.
+        :arg overlay: The overlay object.
+        """
+
+        display = self.displayCtx.getDisplay(overlay)
+        opts    = display.getDisplayOpts()
+
+        name = '{}_{}_zax{}'.format(
+            id(overlay),
+            textures.RenderTextureStack.__name__,
+            self.zax) 
+
+        # If all display/opts properties
+        # are synchronised to the parent,
+        # then we use a texture stack that
+        # might be shared across multiple
+        # views.
+        # 
+        # But if any display/opts properties
+        # are not synchronised, we'll use our
+        # own texture stack. 
+        if not (display.allSyncedToParent() and 
+                opts   .allSyncedToParent()):
+
+            name = '{}_{}'.format(id(self.displayCtx), name)
+
+        if glresources.exists(name):
+            rt = glresources.get(name)
+
+        else:
+            rt = textures.RenderTextureStack(globj)
+            rt.setAxes(self.xax, self.yax)
+            glresources.set(name, rt)
+
+        return rt, name
+
                 
     def _renderModeChange(self, *a):
         """Called when the :attr:`renderMode` property changes."""
@@ -525,6 +558,22 @@ class SliceCanvas(props.HasProperties):
         self._updateRenderTextures()
 
 
+    def _syncOverlayDisplayChanged(self, *a):
+        """Called when the :attr:`.DisplayContext.syncOverlayDisplay`
+        property changes. If the current :attr:`renderMode` is ``prerender``,
+        the :class:`.RenderTextureStack` instances for each overlay are 
+        re-created.
+        
+        This is done because, if all display properties for an overlay are
+        synchronised, then a single ``RenderTextureStack`` can be shared
+        across multiple displays. However, if any display properties are not
+        synchronised, then a separate ``RenderTextureStack`` is needed for
+        the :class:`.DisplayContext` used by this ``SliceCanvas``.
+        """
+        if self.renderMode == 'prerender':
+            self._renderModeChange(self)
+    
+
     def _resolutionLimitChange(self, *a):
         """Called when the :attr:`resolutionLimit` property changes.
 
diff --git a/fsl/fsleyes/gl/textures/rendertexturestack.py b/fsl/fsleyes/gl/textures/rendertexturestack.py
index f6ed133b83b3ba99d67b3ce4f81115ca309f43b7..b332ad265d150c0aa0f6e0f69a27c9e50404017c 100644
--- a/fsl/fsleyes/gl/textures/rendertexturestack.py
+++ b/fsl/fsleyes/gl/textures/rendertexturestack.py
@@ -73,6 +73,13 @@ class RenderTextureStack(object):
         import wx
         wx.GetApp().Bind(wx.EVT_IDLE, self.__textureUpdateLoop)
 
+        log.memory('{}.init ({})'.format(type(self).__name__, id(self)))
+
+        
+    def __del__(self):
+        """Prints a log message."""
+        log.memory('{}.del ({})'.format(type(self).__name__, id(self)))
+
         
     def destroy(self):
         """Must be called when this ``RenderTextureStack`` is no longer needed.