diff --git a/fsl/fsleyes/gl/gl14/glvolume_funcs.py b/fsl/fsleyes/gl/gl14/glvolume_funcs.py index 3b1852abe41467c12ba9d30965c61ee2615deb6d..8fe4900c9eaacdfaa52a846189815915b18c24d2 100644 --- a/fsl/fsleyes/gl/gl14/glvolume_funcs.py +++ b/fsl/fsleyes/gl/gl14/glvolume_funcs.py @@ -106,6 +106,8 @@ def updateShaderState(self): self.shader.unload() + return True + def preDraw(self): """Prepares to draw a slice from the given :class:`.GLVolume` instance. """ diff --git a/fsl/fsleyes/gl/gl21/glvolume_funcs.py b/fsl/fsleyes/gl/gl21/glvolume_funcs.py index 9fabd00017ab5ba6e3eaf95ab6cb2ce60101769b..0d437e29dc847c622fb622918ea63305ad5efcf1 100644 --- a/fsl/fsleyes/gl/gl21/glvolume_funcs.py +++ b/fsl/fsleyes/gl/gl21/glvolume_funcs.py @@ -83,24 +83,28 @@ def updateShaderState(self): self.colourTexture.getCoordinateTransform()) shader.load() + + changed = False - shader.set('useSpline', opts.interpolation == 'spline') - shader.set('imageShape', self.image.shape[:3]) - shader.set('clipLow', clipLow) - shader.set('clipHigh', clipHigh) - shader.set('texZero', texZero) - shader.set('invertClip', opts.invertClipping) - shader.set('useNegCmap', opts.useNegativeCmap) - shader.set('imageIsClip', opts.clipImage is None) - shader.set('img2CmapXform', img2CmapXform) - - shader.set('imageTexture', 0) - shader.set('colourTexture', 1) - shader.set('negColourTexture', 2) - shader.set('clipTexture', 3) + changed |= shader.set('useSpline', opts.interpolation == 'spline') + changed |= shader.set('imageShape', self.image.shape[:3]) + changed |= shader.set('clipLow', clipLow) + changed |= shader.set('clipHigh', clipHigh) + changed |= shader.set('texZero', texZero) + changed |= shader.set('invertClip', opts.invertClipping) + changed |= shader.set('useNegCmap', opts.useNegativeCmap) + changed |= shader.set('imageIsClip', opts.clipImage is None) + changed |= shader.set('img2CmapXform', img2CmapXform) + + changed |= shader.set('imageTexture', 0) + changed |= shader.set('colourTexture', 1) + changed |= shader.set('negColourTexture', 2) + changed |= shader.set('clipTexture', 3) shader.unload() + return changed + def preDraw(self): """Sets up the GL state to draw a slice from the given :class:`.GLVolume` diff --git a/fsl/fsleyes/gl/glvolume.py b/fsl/fsleyes/gl/glvolume.py index 5e07775dce66653aecc7c52e4ca9a74617e70362..261488e83d55658200dd5818e85cf0ad32b9af1d 100644 --- a/fsl/fsleyes/gl/glvolume.py +++ b/fsl/fsleyes/gl/glvolume.py @@ -265,11 +265,10 @@ class GLVolume(globject.GLImageObject): def update(*a): self.notify() - def shaderUpdate(*a): if self.ready(): - fslgl.glvolume_funcs.updateShaderState(self) - self.notify() + if fslgl.glvolume_funcs.updateShaderState(self): + self.notify() def colourUpdate(*a): self.refreshColourTextures() diff --git a/fsl/fsleyes/gl/shaders/glsl/program.py b/fsl/fsleyes/gl/shaders/glsl/program.py index 49275d54e68b2d3830ad4a546af951d1b629a488..9e3c381c7533743cdea4c0b05c02d1026ca46184 100644 --- a/fsl/fsleyes/gl/shaders/glsl/program.py +++ b/fsl/fsleyes/gl/shaders/glsl/program.py @@ -149,6 +149,13 @@ class GLSLShader(object): self.vertUniforms, self.fragUniforms) + # We cache the most recent value for + # every uniform. When a call to set() + # is made, if the value is unchanged, + # we skip the GL call. + self.values = {n : None for n in self.positions.keys()} + + # Buffers for vertex attributes self.buffers = {} for att in self.vertAttributes: @@ -234,7 +241,16 @@ class GLSLShader(object): def set(self, name, value): - """Sets the value for the specified GLSL ``uniform`` variable. """ + """Sets the value for the specified GLSL ``uniform`` variable. + + The ``GLSLShader`` keeps a copy of the value of every uniform, to + avoid unnecessary GL calls. + + :returns: ``True`` if the value was changed, ``False`` otherwise. + """ + + if self.values[name] == value: + return False vPos = self.positions[name] vType = self.types[ name] @@ -250,6 +266,8 @@ class GLSLShader(object): setfunc(vPos, value) + return True + def setAtt(self, name, value, divisor=None): """Sets the value for the specified GLSL ``attribute`` variable.