From 93bd9eb1430c68bca4f851805f69d39466678e4e Mon Sep 17 00:00:00 2001 From: Paul McCarthy <pauld.mccarthy@gmail.com> Date: Thu, 4 Feb 2016 15:14:01 +0000 Subject: [PATCH] First GLTensor draw was failing, because i was calling GLSLShader.loadAtts before setting the vertex attribute divisor. Other associated changes to initial refresh - it now occurs after all eigenvector/value textures are ready. --- fsl/fsleyes/gl/gl21/gltensor_funcs.py | 17 +++++++++++++---- fsl/fsleyes/gl/glvector.py | 12 +++++++----- fsl/utils/async.py | 9 +++++++-- 3 files changed, 27 insertions(+), 11 deletions(-) diff --git a/fsl/fsleyes/gl/gl21/gltensor_funcs.py b/fsl/fsleyes/gl/gl21/gltensor_funcs.py index 15554b661..65a99bd31 100644 --- a/fsl/fsleyes/gl/gl21/gltensor_funcs.py +++ b/fsl/fsleyes/gl/gl21/gltensor_funcs.py @@ -60,6 +60,10 @@ import glvector_funcs def init(self): """Creates textures for the tensor eigenvalue and eigenvector images, and calls :func:`compileShaders` and :func:`updateShaderState`. + + :returns: A list of ``Thread`` instances, one for each of the + :class:`.ImageTexture` instances that are created. See + the ``init`` parameter to :meth:`.GLVector.__init__`. """ image = self.image @@ -74,8 +78,9 @@ def init(self): def vPrefilter(d): return d.transpose((3, 0, 1, 2)) - names = ['v1', 'v2', 'v3', 'l1', 'l2', 'l3'] - imgs = [ v1, v2, v3, l1, l2, l3] + names = ['v1', 'v2', 'v3', 'l1', 'l2', 'l3'] + imgs = [ v1, v2, v3, l1, l2, l3] + texThreads = [] for name, img in zip(names, imgs): texName = '{}_{}_{}'.format(type(self).__name__, name, id(img)) @@ -96,6 +101,8 @@ def init(self): normalise=True, prefilter=prefilter) + texThreads.append(tex.refreshThread()) + setattr(self, '{}Texture'.format(name), tex) self.shader = None @@ -103,6 +110,8 @@ def init(self): compileShaders(self) updateShaderState(self) + return texThreads + def destroy(self): """Deletes the :class:`.GLSLShader`, and all textures. """ @@ -262,10 +271,10 @@ def draw(self, zpos, xform=None): # Set divisor to 1, so we use one set of # voxel coordinates for every sphere drawn - shader.loadAtts() shader.setAtt('voxel', voxels, divisor=1) shader.set( 'voxToDisplayMat', xform) - + shader.loadAtts() + arbdi.glDrawElementsInstancedARB( gl.GL_QUADS, self.nVertices, gl.GL_UNSIGNED_INT, None, nVoxels) diff --git a/fsl/fsleyes/gl/glvector.py b/fsl/fsleyes/gl/glvector.py index 3574a7bc2..6e97d1efb 100644 --- a/fsl/fsleyes/gl/glvector.py +++ b/fsl/fsleyes/gl/glvector.py @@ -131,8 +131,11 @@ class GLVector(globject.GLImageObject): :arg init: An optional function to be called when all of the :class:`.ImageTexture` instances associated with - this ``GLVector`` have been initialised. - + this ``GLVector`` have been initialised. If this + function does any initialisation on one or more + separate threads, it should return references to + those threads so that this method is able to + determine when initialisation is complete. """ if vectorImage is None: vectorImage = image @@ -177,9 +180,8 @@ class GLVector(globject.GLImageObject): self.refreshColourTextures() def texRefresh(): - if init is not None: - init() - self.notify() + if init is not None: async.wait(init(), self.notify) + else: self.notify() async.wait([self.refreshImageTexture(), self.refreshAuxTexture('modulate'), diff --git a/fsl/utils/async.py b/fsl/utils/async.py index bc551d077..73330044b 100644 --- a/fsl/utils/async.py +++ b/fsl/utils/async.py @@ -34,6 +34,7 @@ the task (via :func:`idle`). import Queue import logging import threading +import collections log = logging.getLogger(__name__) @@ -173,13 +174,17 @@ def wait(threads, task, *args, **kwargs): If a ``wx.App`` is not running, this function ``join``s the threads directly instead of creating a new ``Thread`` to do so. - :arg threads: A sequence of ``Thread`` instances to join. Elements in the - sequence may be ``None``. + :arg threads: A ``Thread``, or a sequence of ``Thread`` instances to + join. Elements in the sequence may be ``None``. :arg task: The task to run. All other arguments are passed to the ``task`` function. """ + + if not isinstance(threads, collections.Sequence): + threads = [threads] + haveWX = _haveWX() def joinAll(): -- GitLab