Skip to content
Snippets Groups Projects
Commit aeeaac98 authored by Paul McCarthy's avatar Paul McCarthy
Browse files

async.wait related updates to other GL types.

parent 8d40ddf2
No related branches found
No related tags found
No related merge requests found
......@@ -9,12 +9,13 @@ functionality to render an :class:`.Image` overlay as a label/atlas image.
"""
import OpenGL.GL as gl
import OpenGL.GL as gl
import fsl.fsleyes.gl as fslgl
import resources as glresources
import globject
import textures
import fsl.fsleyes.gl as fslgl
import fsl.utils.async as async
import resources as glresources
import globject
import textures
class GLLabel(globject.GLImageObject):
......@@ -99,18 +100,17 @@ class GLLabel(globject.GLImageObject):
self.notify()
def shaderUpdate(*a):
fslgl.gllabel_funcs.updateShaderState(self)
self.notify()
if self.ready():
fslgl.gllabel_funcs.updateShaderState(self)
self.notify()
def shaderCompile(*a):
fslgl.gllabel_funcs.compileShaders(self)
fslgl.gllabel_funcs.updateShaderState(self)
self.notify()
shaderUpdate()
def lutUpdate(*a):
self.refreshLutTexture()
fslgl.gllabel_funcs.updateShaderState(self)
self.notify()
shaderUpdate()
def lutChanged(*a):
if self.__lut is not None:
......@@ -124,14 +124,13 @@ class GLLabel(globject.GLImageObject):
lutUpdate()
def imageRefresh(*a):
self.refreshImageTexture()
fslgl.gllabel_funcs.updateShaderState(self)
async.wait([self.refreshImageTexture()], shaderUpdate)
def imageUpdate(*a):
self.imageTexture.set(volume=opts.volume,
resolution=opts.resolution)
fslgl.gllabel_funcs.updateShaderState(self)
async.wait([self.imageTexture.refreshThread()], shaderUpdate)
self.__lut = opts.lut
......@@ -184,13 +183,13 @@ class GLLabel(globject.GLImageObject):
opts.removeSyncChangeListener('resolution', name)
def setAxes(self, xax, yax):
"""Overrides :meth:`.GLImageObject.setAxes`. Updates the shader
program state,
program state.
"""
globject.GLImageObject.setAxes(self, xax, yax)
fslgl.gllabel_funcs.updateShaderState(self)
if self.ready():
fslgl.gllabel_funcs.updateShaderState(self)
def refreshImageTexture(self):
......@@ -211,7 +210,7 @@ class GLLabel(globject.GLImageObject):
if self.imageTexture is not None:
if self.imageTexture.getTextureName() == texName:
return
return None
self.imageTexture.deregister(self.name)
glresources.delete(self.imageTexture.getTextureName())
......@@ -220,10 +219,13 @@ class GLLabel(globject.GLImageObject):
texName,
textures.ImageTexture,
texName,
self.image)
self.image,
notify=False)
self.imageTexture.register(self.name, self.__imageTextureChanged)
return self.imageTexture.refreshThread()
def refreshLutTexture(self, *a):
"""Refreshes the :class:`.LookupTableTexture` which stores the
......
......@@ -67,9 +67,12 @@ class GLLineVector(glvector.GLVector):
if isinstance(image, tensorimage.TensorImage): vecImage = image.V1()
else: vecImage = image
glvector.GLVector.__init__(self, image, display, vectorImage=vecImage)
fslgl.gllinevector_funcs.init(self)
glvector.GLVector.__init__(self,
image,
display,
vectorImage=vecImage,
init=lambda: fslgl.gllinevector_funcs.init(
self))
def update(*a):
self.notify()
......
......@@ -14,6 +14,7 @@ import numpy as np
import fsl.fsleyes.gl as fslgl
import fsl.fsleyes.colourmaps as colourmaps
import fsl.utils.async as async
import glvolume
......@@ -49,34 +50,29 @@ class GLMask(glvolume.GLVolume):
def update(*a):
self.notify()
def shaderCompile(*a):
fslgl.glvolume_funcs.compileShaders( self)
fslgl.glvolume_funcs.updateShaderState(self)
self.notify()
def shaderUpdate(*a):
fslgl.glvolume_funcs.updateShaderState(self)
self.notify()
if self.ready():
fslgl.glvolume_funcs.updateShaderState(self)
self.notify()
def shaderCompile(*a):
fslgl.glvolume_funcs.compileShaders(self)
shaderUpdate()
def colourUpdate(*a):
self.refreshColourTextures()
fslgl.glvolume_funcs.updateShaderState(self)
self.notify()
shaderUpdate()
def imageRefresh(*a):
self.refreshImageTexture()
fslgl.glvolume_funcs.updateShaderState(self)
self.notify()
async.wait([self.refreshImageTexture()], shaderUpdate)
def imageUpdate(*a):
volume = opts.volume
resolution = opts.resolution
self.imageTexture.set(volume=volume, resolution=resolution)
fslgl.glvolume_funcs.updateShaderState(self)
self.notify()
async.wait([self.refreshThread()], shaderUpdate)
display.addListener('alpha', name, colourUpdate, weak=False)
display.addListener('brightness', name, colourUpdate, weak=False)
......
......@@ -13,6 +13,7 @@ import numpy as np
import OpenGL.GL as gl
import fsl.data.tensorimage as tensorimage
import fsl.utils.async as async
import fsl.fsleyes.gl as fslgl
import fsl.fsleyes.gl.glvector as glvector
......@@ -75,9 +76,9 @@ class GLRGBVector(glvector.GLVector):
image,
display,
prefilter=np.abs,
vectorImage=vecImage)
fslgl.glrgbvector_funcs.init(self)
vectorImage=vecImage,
init=lambda: fslgl.glrgbvector_funcs.init(
self))
self.displayOpts.addListener('interpolation',
self.name,
......@@ -107,7 +108,7 @@ class GLRGBVector(glvector.GLVector):
if opts.interpolation == 'none': interp = gl.GL_NEAREST
else: interp = gl.GL_LINEAR
glvector.GLVector.refreshImageTexture(self, interp)
return glvector.GLVector.refreshImageTexture(self, interp)
def __dataChanged(self, *a):
......@@ -126,12 +127,13 @@ class GLRGBVector(glvector.GLVector):
if opts.interpolation == 'none': interp = gl.GL_NEAREST
else: interp = gl.GL_LINEAR
texChange = self.imageTexture.set(interp=interp)
self.updateShaderState()
self.imageTexture.set(interp=interp)
def onRefresh():
self.updateShaderState()
self.notify()
# See comments in GLVolume.addDisplayListeners about this
if not texChange:
self.notify()
async.wait([self.imageTexture.refreshThread()], onRefresh)
def compileShaders(self):
......
......@@ -41,8 +41,9 @@ class GLTensor(glvector.GLVector):
image,
display,
prefilter=np.abs,
vectorImage=image.V1())
fslgl.gltensor_funcs.init(self)
vectorImage=image.V1(),
init=lambda: fslgl.gltensor_funcs.init(
self))
def destroy(self):
......@@ -65,8 +66,9 @@ class GLTensor(glvector.GLVector):
opts = self.displayOpts
def shaderUpdate(*a):
self.updateShaderState()
self.notify()
if self.ready():
self.updateShaderState()
self.notify()
opts.addListener('lighting', name, shaderUpdate, weak=False)
opts.addListener('tensorResolution', name, shaderUpdate, weak=False)
......
......@@ -14,6 +14,7 @@ import numpy as np
import OpenGL.GL as gl
import fsl.data.image as fslimage
import fsl.utils.async as async
import fsl.fsleyes.colourmaps as fslcm
import resources as glresources
import textures
......@@ -92,7 +93,12 @@ class GLVector(globject.GLImageObject):
"""
def __init__(self, image, display, prefilter=None, vectorImage=None):
def __init__(self,
image,
display,
prefilter=None,
vectorImage=None,
init=None):
"""Create a ``GLVector`` object bound to the given image and display.
Initialises the OpenGL data required to render the given image.
......@@ -122,6 +128,11 @@ class GLVector(globject.GLImageObject):
``vectorImage`` parameter can be used to specify
an ``Image`` instance which does contain the
vector data.
:arg init: An optional function to be called when all of the
:class:`.ImageTexture` instances associated with
this ``GLVector`` have been initialised.
"""
if vectorImage is None: vectorImage = image
......@@ -140,7 +151,8 @@ class GLVector(globject.GLImageObject):
self.yColourTexture = textures.ColourMapTexture('{}_y' .format(name))
self.zColourTexture = textures.ColourMapTexture('{}_z' .format(name))
self.cmapTexture = textures.ColourMapTexture('{}_cm'.format(name))
self.shader = None
self.modulateImage = None
self.clipImage = None
self.colourImage = None
......@@ -162,12 +174,19 @@ class GLVector(globject.GLImageObject):
if opts.clipImage is not None: self.registerAuxImage('clip')
self.addListeners()
self.refreshImageTexture()
self.refreshAuxTexture('modulate')
self.refreshAuxTexture('clip')
self.refreshAuxTexture('colour')
self.refreshColourTextures()
def texRefresh():
if init is not None:
init()
self.notify()
async.wait([self.refreshImageTexture(),
self.refreshAuxTexture('modulate'),
self.refreshAuxTexture('clip'),
self.refreshAuxTexture('colour')],
texRefresh)
def destroy(self):
"""Must be called when this ``GLVector`` is no longer needed. Deletes
......@@ -210,7 +229,8 @@ class GLVector(globject.GLImageObject):
"""Returns ``True`` if this ``GLVector`` is ready to be drawn,
``False`` otherwise.
"""
return all((self.imageTexture is not None,
return all((self.shader is not None,
self.imageTexture is not None,
self.modulateTexture is not None,
self.clipTexture is not None,
self.colourTexture is not None,
......@@ -232,50 +252,47 @@ class GLVector(globject.GLImageObject):
def update(*a):
self.notify()
def shaderUpdate(*a):
if self.ready():
self.updateShaderState()
self.notify()
def modUpdate( *a):
self.deregisterAuxImage('modulate')
self.registerAuxImage( 'modulate')
self.refreshAuxTexture( 'modulate')
self.updateShaderState()
self.registerAuxImage( 'modulate')
async.wait([self.refreshAuxTexture( 'modulate')], shaderUpdate)
def clipUpdate( *a):
self.deregisterAuxImage('clip')
self.registerAuxImage( 'clip')
self.refreshAuxTexture( 'clip')
self.updateShaderState()
async.wait([self.refreshAuxTexture( 'clip')], shaderUpdate)
def colourUpdate( *a):
self.deregisterAuxImage('colour')
self.registerAuxImage( 'colour')
self.refreshAuxTexture( 'colour')
def onRefresh():
self.compileShaders()
self.refreshColourTextures()
shaderUpdate()
async.wait([self.refreshAuxTexture( 'colour')], onRefresh)
self.compileShaders()
self.refreshColourTextures()
self.updateShaderState()
def cmapUpdate(*a):
self.refreshColourTextures()
self.updateShaderState()
self.notify()
def shaderUpdate(*a):
self.updateShaderState()
self.notify()
shaderUpdate()
def shaderCompile(*a):
self.compileShaders()
self.updateShaderState()
self.notify()
shaderUpdate()
def imageRefresh(*a):
self.refreshImageTexture()
self.updateShaderState()
async.wait([self.refreshImageTexture()], shaderUpdate)
def imageUpdate(*a):
self.imageTexture.set(resolution=opts.resolution)
self.updateShaderState()
async.wait([self.imageTexture.refreshThread()], shaderUpdate)
display.addListener('alpha', name, cmapUpdate, weak=False)
display.addListener('brightness', name, cmapUpdate, weak=False)
......@@ -373,10 +390,13 @@ class GLVector(globject.GLImageObject):
nvals=3,
interp=interp,
normalise=True,
prefilter=realPrefilter)
prefilter=realPrefilter,
notify=False)
self.imageTexture.register(self.name, self.__textureChanged)
return self.imageTexture.refreshThread()
def compileShaders(self):
"""This method must be provided by subclasses (the
......@@ -408,8 +428,10 @@ class GLVector(globject.GLImageObject):
imageAttr = '{}Image' .format(which)
optsAttr = '{}Opts' .format(which)
texAttr = '{}Texture'.format(which)
image = getattr(self.displayOpts, imageAttr)
tex = getattr(self, texAttr)
if image is None or image == 'none':
image = None
......@@ -426,8 +448,12 @@ class GLVector(globject.GLImageObject):
def volumeChange(*a):
self.refreshAuxTexture(which)
self.notify()
def onRefresh():
self.updateShaderState()
self.notify()
tex.set(volume=opts.volume)
async.wait([tex.refreshThread()], onRefresh)
# We set overwrite=True, because
# the modulate/clip/colour images
......@@ -508,12 +534,15 @@ class GLVector(globject.GLImageObject):
textures.ImageTexture,
texName,
image,
normalise=norm)
normalise=norm,
notify=False)
tex.register(self.name, self.__textureChanged)
setattr(self, texAttr, tex)
return tex.refreshThread()
def refreshColourTextures(self, colourRes=256):
"""Called when the component colour maps need to be updated, when one
......
......@@ -264,25 +264,20 @@ class GLVolume(globject.GLImageObject):
def update(*a):
self.notify()
def colourUpdate(*a):
self.refreshColourTextures()
if self.ready():
fslgl.glvolume_funcs.updateShaderState(self)
self.notify()
def shaderUpdate(*a):
if self.ready():
fslgl.glvolume_funcs.updateShaderState(self)
self.notify()
def onTextureRefresh():
def colourUpdate(*a):
self.refreshColourTextures()
if self.ready():
fslgl.glvolume_funcs.updateShaderState(self)
self.notify()
shaderUpdate()
def imageRefresh(*a):
async.wait([self.refreshImageTexture()], onTextureRefresh)
async.wait([self.refreshImageTexture()], shaderUpdate)
def imageUpdate(*a):
volume = opts.volume
......@@ -304,12 +299,12 @@ class GLVolume(globject.GLImageObject):
notify=False)
waitfor.append(self.clipTexture.refreshThread())
async.wait(waitfor, onTextureRefresh)
async.wait(waitfor, shaderUpdate)
def clipUpdate(*a):
self.deregisterClipImage()
self.registerClipImage()
async.wait([self.refreshClipTexture()], onTextureRefresh)
async.wait([self.refreshClipTexture()], shaderUpdate)
display.addListener('alpha', lName, colourUpdate, weak=False)
opts .addListener('displayRange', lName, colourUpdate, weak=False)
......@@ -397,6 +392,11 @@ class GLVolume(globject.GLImageObject):
:class:`.Image` data. This is performed through the :mod:`.resources`
module, so the image texture can be shared between multiple
``GLVolume`` instances.
:returns: A reference to the ``Thread`` instance which is
asynchronously updating the :class:`.ImageTexture`,
or ``None`` if the texture is updated - see the
:meth:`.ImageTexture.refreshThread` method.
"""
opts = self.displayOpts
......@@ -447,9 +447,13 @@ class GLVolume(globject.GLImageObject):
self.clipOpts = clipOpts
def updateClipTexture(*a):
def onRefresh():
fslgl.glvolume_funcs.updateShaderState(self)
self.notify()
self.clipTexture.set(volume=clipOpts.volume)
async.wait([self.clipTexture.refreshThread()],
fslgl.glvolume_funcs.updateShaderState, self)
async.wait([self.clipTexture.refreshThread()], onRefresh)
clipOpts.addListener('volume',
self.name,
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment