From 12ac1e177d6eb6f628c2acb3c185724b0b2ceedb Mon Sep 17 00:00:00 2001 From: Paul McCarthy <pauld.mccarthy@gmail.com> Date: Fri, 13 Nov 2015 11:50:21 +0000 Subject: [PATCH] Bugfix - when running in prerender mode, and display sync is off, SliceCanvas/LightBoxCanvases need to create separate RenderTextureStacks, instead of sharing a single one. --- fsl/fsleyes/gl/lightboxcanvas.py | 16 +--- fsl/fsleyes/gl/slicecanvas.py | 75 +++++++++++++++---- fsl/fsleyes/gl/textures/rendertexturestack.py | 7 ++ 3 files changed, 71 insertions(+), 27 deletions(-) diff --git a/fsl/fsleyes/gl/lightboxcanvas.py b/fsl/fsleyes/gl/lightboxcanvas.py index fa193d337..3a6a62721 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 b91587a47..6d062a8ef 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 f6ed133b8..b332ad265 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. -- GitLab