From 0e73962ca3cb29f09fade08a87c81930f79296ad Mon Sep 17 00:00:00 2001
From: Paul McCarthy <pauld.mccarthy@gmail.com>
Date: Tue, 29 Dec 2015 14:45:22 +0000
Subject: [PATCH] Some documentation for GLSL package modules.

---
 fsl/fsleyes/gl/glsl/parse.py   | 18 +++++--
 fsl/fsleyes/gl/glsl/program.py | 99 ++++++++++++++++++++++++++++++++--
 fsl/fsleyes/gl/shaders.py      |  2 +-
 setup.py                       |  1 +
 4 files changed, 110 insertions(+), 10 deletions(-)

diff --git a/fsl/fsleyes/gl/glsl/parse.py b/fsl/fsleyes/gl/glsl/parse.py
index abe2d591a..e4ed5ea1b 100644
--- a/fsl/fsleyes/gl/glsl/parse.py
+++ b/fsl/fsleyes/gl/glsl/parse.py
@@ -1,7 +1,7 @@
 #!/usr/bin/env python
 #
 # parse.py - Simple parser for extracting information about a GLSL program.
-
+# 
 # Author: Paul McCarthy <pauldmccarthy@gmail.com>
 #
 # Based on work by Nicolas P. Rougier
@@ -51,11 +51,12 @@ about the program.
 
 
 from __future__ import print_function
-
+import sys
 import logging
 
 import pyparsing as pp
 
+
 log = logging.getLogger(__name__)
 
 
@@ -167,11 +168,14 @@ def parseGLSL(source):
     return decs
 
 
-if __name__ == '__main__':
-    import sys
+def main():
+    """If this module is executed as a script, this function is called.
+    It expects a path to a ``glsl`` file as a single parameter. This file
+    is parsed, and information about it printed to standard output.
+    """
 
     if len(sys.argv) != 2:
-        print('Usage: glslparse.py file.glsl')
+        print('Usage: {}.py file.glsl'.format(__name__))
         sys.exit(0)
 
     infile = sys.argv[1]
@@ -187,3 +191,7 @@ if __name__ == '__main__':
         print('\n--{}--\n'.format(d.upper()))
         for t, n in v:
             print('{}: {}'.format(t, n))
+
+            
+if __name__ == '__main__':
+    main()
diff --git a/fsl/fsleyes/gl/glsl/program.py b/fsl/fsleyes/gl/glsl/program.py
index 91bbf3517..60ee3b04a 100644
--- a/fsl/fsleyes/gl/glsl/program.py
+++ b/fsl/fsleyes/gl/glsl/program.py
@@ -30,14 +30,85 @@ GLSL_ATTRIBUTE_TYPES = {
     'vec3'          : (gl.GL_FLOAT, 3),
     'vec4'          : (gl.GL_FLOAT, 3)
 }
+"""This dictionary contains mappings between GLSL data types, and their
+corresponding GL types and sizes.
+"""
 
 
 class ShaderProgram(object):
+    """The ``ShaderProgram`` class encapsulates information and logic about
+    a GLSL 1.20 shader program, comprising a vertex shader and a fragment
+    shader. It provides methods to set shader attribute and uniform values,
+    to configure attributes, and to load/unload the program. Furthermore,
+    the ``ShaderProgram`` makes sure that all uniform and attribut variables
+    are converted to the appropriate type. The following methods are available
+    on a ``ShaderProgram``:
+
+    
+    .. autosummary::
+       :nosignatures:
+
+       load
+       unload
+       delete
+       loadAtts
+       unloadAtts
+       set
+       setAtt
+       setIndices
+
+
+    Typical usage of a ``ShaderProgram`` will look something like the
+    following::
+
+        vertSrc = 'vertex shader source'
+        fragSrc = 'vertex shader source'
+
+        program = ShaderProgram(vertSrc, fragSrc)
+
+        # Load the program
+        program.load()
+
+        # Set some uniform values
+        program.set('lighting', True)
+        program.set('lightPos', [0, 0, -1])
+
+        # Create and set vertex attributes
+        vertices, normals = createVertices()
+    
+        program.setAtt('vertex', vertices)
+        program.setAtt('normal', normals)
+
+        # Load the attributes
+        program.loadAtts()
+
+        # Draw the scene
+        gl.glDrawArrays(gl.GL_TRIANGLES, 0, len(vertices))
 
-    def __init__(self,
-                 vertSrc,
-                 fragSrc,
-                 indexed=False):
+        # Clear the GL state
+        program.unload()
+        program.unloadAtts()
+
+
+        # Delete the program when
+        # we no longer need it
+        program.delete()
+    """
+    
+
+    def __init__(self, vertSrc, fragSrc, indexed=False):
+        """Create a ``ShaderProgram``.
+
+        :arg vertSrc: String containing vertex shader source code.
+        
+        :arg fragSrc: String containing fragment shader source code.
+        
+        :arg indexed: If ``True``, it is assumed that the vertices processed
+                      by this shader program will be drawn using an index
+                      array.  A vertex buffer object is created to store
+                      vertex indices - this buffer is expected to be populated
+                      via the :meth:`setIndices` method.
+        """
 
         self.program     = self.__compile(vertSrc, fragSrc)
         
@@ -95,10 +166,16 @@ class ShaderProgram(object):
 
             
     def load(self):
+        """Loads this ``ShaderProgram`` into the GL state.
+        """
         gl.glUseProgram(self.program)
 
 
     def loadAtts(self):
+        """Binds all of the shader program ``attribute`` variables - you
+        must set the data for each attribute via :meth:`setAtt` before
+        calling this method.
+        """
         for att in self.vertAttributes:
 
             aPos           = self.positions[          att]
@@ -124,6 +201,8 @@ class ShaderProgram(object):
 
             
     def unloadAtts(self):
+        """Disables all vertex attributes, and unbinds associated vertex buffers.
+        """
         for att in self.vertAttributes:
             gl.glDisableVertexAttribArray(self.positions[att])
 
@@ -140,10 +219,12 @@ class ShaderProgram(object):
 
         
     def unload(self):
+        """Unloads the GL shader program. """
         gl.glUseProgram(0)
 
 
     def delete(self):
+        """Deletes all GL resources managed by this ``ShaderProgram`. """
         gl.glDeleteProgram(self.program)
 
         for buf in self.buffers.values():
@@ -152,6 +233,7 @@ class ShaderProgram(object):
         
         
     def set(self, name, value):
+        """Sets the value for the specified GLSL ``uniform`` variable. """
 
         vPos  = self.positions[name]
         vType = self.types[    name]
@@ -169,6 +251,11 @@ class ShaderProgram(object):
 
 
     def setAtt(self, name, value, divisor=None):
+        """Sets the value for the specified GLSL ``attribute`` variable.
+
+        :arg divisor: If specified, this value is used as a divisor for this
+                      attribute via the ``glVetexAttribDivisor`` function.
+        """ 
 
         aType    = self.types[  name]
         aBuf     = self.buffers[name]
@@ -196,6 +283,10 @@ class ShaderProgram(object):
 
 
     def setIndices(self, indices):
+        """If an index array is to be used by this ``ShaderProgram`` (see the
+        ``indexed`` argument to :meth:`__init__`), the index array may be set
+        via this method.
+        """
 
         if self.indexBuffer is None:
             raise RuntimeError('Shader program was not '
diff --git a/fsl/fsleyes/gl/shaders.py b/fsl/fsleyes/gl/shaders.py
index 5a9161f02..df7a03ea3 100644
--- a/fsl/fsleyes/gl/shaders.py
+++ b/fsl/fsleyes/gl/shaders.py
@@ -22,7 +22,7 @@ following functions:
    compileShaders
 
 
-Some functions are also provided which make setting program variables a bit
+Some functions are also provided which make setting ARB program variables a bit
 less painful:
 
 
diff --git a/setup.py b/setup.py
index d50084c83..34dcd079c 100644
--- a/setup.py
+++ b/setup.py
@@ -50,6 +50,7 @@ setup(
 
     install_requires=[
         'pyopengl>=3.1.0',
+        'pyparsing>=2.0.3',
         'numpy>=1.8.1',
         'scipy>=0.14.0',
         'matplotlib>=1.3.1',
-- 
GitLab