diff --git a/fsl/fsleyes/gl/__init__.py b/fsl/fsleyes/gl/__init__.py
index 2029ae052b3d728fb37c7f16da173cc00b435ffc..e6480376e86b96234711b349e5037bf7860dc556 100644
--- a/fsl/fsleyes/gl/__init__.py
+++ b/fsl/fsleyes/gl/__init__.py
@@ -175,11 +175,15 @@ Other things in the ``gl`` package
 ----------------------------------
 
 
-:mod:`.textures`
-:mod:`.routines`
-:mod:`.resources`
-:mod:`.shaders`
+In addition to the *canvases* and *objects* described above, the ``gl``
+package also contains the following:
 
+.. autosummary::
+
+   ~fsl.fsleyes.gl.textures
+   ~fsl.fsleyes.gl.routines
+   ~fsl.fsleyes.gl.resources
+   ~fsl.fsleyes.gl.shaders
 """
 
 import logging 
@@ -239,7 +243,7 @@ def bootstrap(glVersion=None):
 
 
     After the :func:`boostrap` function has been called, the following
-    package-level attributes will be available:
+    package-level attributes will be available on the ``gl`` package:
 
 
     ====================== ====================================================
@@ -257,6 +261,9 @@ def bootstrap(glVersion=None):
 
     ``glmodel_funcs``      The version-specific module containing functions for
                            rendering :class:`.GLModel` instances.
+    
+    ``gllabel_funcs``      The version-specific module containing functions for
+                           rendering :class:`.GLLabel` instances. 
     ====================== ====================================================
     
 
@@ -383,15 +390,15 @@ def getWXGLContext(parent=None):
     
       - A :class:`wx.glcanvas.GLContext` instance
     
-      - If a context instance has previously been created, the second
-        return value is ``None``. Other a dummy
-        :class:`wx.glcanvas.GLCanvas` instance is returned. This canvas
-        should be destroyed by the caller when it is safe to do so. This
-        seems to primarily be a problem under Linux/GTK - it does not
-        seem to be possible to destroy the dummy canvas immediately after
-        creating the context. So the calling code needs to destroy it
-        at some point in the future (possibly after another, real
-        GLCanvas has been created, and set as the context target).
+      - If a context instance has previously been created, the second return
+        value is ``None``. Otherwise, a dummy :class:`wx.glcanvas.GLCanvas`
+        instance is returned. This canvas should be destroyed by the caller
+        when it is safe to do so. This seems to primarily be a problem under
+        Linux/GTK - it does not seem to be possible to destroy the dummy
+        canvas immediately after creating the context. So the calling code
+        needs to destroy it at some point in the future (possibly after
+        another, real ``GLCanvas`` has been created, and set as the context
+        target).
     """
 
     import sys
@@ -476,15 +483,17 @@ def getOSMesaContext():
 
 
 class OSMesaCanvasTarget(object):
-    """Superclass for canvas objects which support off-screen rendering using
+    """Base class for canvas objects which support off-screen rendering using
     OSMesa.
     """
     
     def __init__(self, width, height):
-        """Creates an off-screen buffer to be used as the render target.
+        """Create an ``OSMesaCanvasTarget``. An off-screen buffer, to be used
+        as the render target, is created.
 
         :arg width:    Width in pixels
         :arg height:   Height in pixels
+
         """
         import OpenGL.arrays as glarrays 
         self.__width  = width
@@ -568,15 +577,24 @@ class OSMesaCanvasTarget(object):
 
 
 class WXGLCanvasTarget(object):
-    """Superclass for :class:`wx.glcanvas.GLCanvas` objects objects.
+    """Base class for :class:`wx.glcanvas.GLCanvas` objects.
+
+    It is assumed that subclasses of this base class are also subclasses of
+    :class:`wx.glcanvas.GLCanvas`. Sub-classes must override the following
+    methods:
 
-    It is assumed that subclasses of this superclass are also subclasses of
-    :class:`wx.glcanvas.GLCanvas`
+    .. autosummary::
+       :nosignatures:
+
+       _initGL
+       _draw
     """
 
 
     def __init__(self):
-        """Binds :attr:`wx.EVT_PAINT` events to the :meth:`_mainDraw` method.
+        """Create a ``WXGLCanasTarget``.
+
+        Binds :attr:`wx.EVT_PAINT` events to the :meth:`_mainDraw` method.
         """
 
         import wx
@@ -586,18 +604,15 @@ class WXGLCanvasTarget(object):
     
 
     def _initGL(self):
-        """Must be implemented by subclasses.
-
-        This method should perform any OpenGL data initialisation required for
-        rendering.
+        """This method should perform any OpenGL data initialisation required
+        for rendering. Must be implemented by subclasses.
         """
         raise NotImplementedError()
 
 
     def _draw(self, *a):
-        """Must be implemented by subclasses.
-
-        This method should implement the OpenGL drawing logic.
+        """This method should implement the OpenGL drawing logic. Must be
+        implemented by subclasses.
         """
         raise NotImplementedError()
  
diff --git a/fsl/fsleyes/gl/globject.py b/fsl/fsleyes/gl/globject.py
index 752546b03ad719012068aa09db2c4201f30293e1..2b17f6eae9407761be70eba8f57fd96d1cb37558 100644
--- a/fsl/fsleyes/gl/globject.py
+++ b/fsl/fsleyes/gl/globject.py
@@ -1,15 +1,15 @@
 #!/usr/bin/env python
 #
-# globject.py - Mapping between overlay types and OpenGL representations.
+# globject.py - The GLObject class.
 #
 # Author: Paul McCarthy <pauldmccarthy@gmail.com>
 #
-"""This module defines the :class:`GLObject` class, which is a superclass for
+"""This module provides the :class:`GLObject` class, which is a superclass for
 all 2D representations of objects in OpenGL.
 
-This module also provides the :func:`createGLObject` function, which provides
-mappings between overlay objects and their corresponding OpenGL
-representation.
+This module also provides the :func:`getGLObjectType` and
+:func:`createGLObject` functions, which provide mappings between overlay
+types and their corresponding OpenGL representations.
 """
 
 import logging
@@ -25,7 +25,7 @@ log = logging.getLogger(__name__)
 
 def getGLObjectType(overlayType):
     """This function returns an appropriate :class:`GLObject` type for the
-    given :attr:`.Display.overlayType`.
+    given :attr:`.Display.overlayType` value.
     """
 
     import glvolume
@@ -63,9 +63,13 @@ def createGLObject(overlay, display):
 
 
 class GLObject(object):
-    """The :class:`GLObject` class is a superclass for all 2D OpenGL
-    objects.
+    """The :class:`GLObject` class is a base class for all 2D OpenGL
+    objects displayed in *FSLeyes*.
 
+    
+    **Instance attributes**
+
+    
     The following attributes will always be available on ``GLObject``
     instances:
 
@@ -78,7 +82,48 @@ class GLObject(object):
                   corresponds to the vertical screen axis.
     
       - ``zax``:  Index of the display coordinate system axis that 
-                  corresponds to the depth screen axis. 
+                  corresponds to the depth screen axis.
+
+
+    **Update listeners**
+    
+
+    Entities which are interested in changes to a ``GLObject`` representation
+    may register as *update listeners*, via the :meth:`addUpdateListener`
+    method. Whenever the state of a ``GLObject`` changes, all update listeners
+    will be called. It is the resposibility of sub-class implementations to
+    call the :meth:`onUpdate` method to facilitate this notification process.
+
+
+    **Sub-class resposibilities***
+
+    
+    Sub-class implementations must do the following:
+    
+     - Call :meth:`__init__`.
+
+     - Call :meth:`onUpdate` whenever its OpenGL representation changes.
+
+     - Override the following methods:
+    
+       .. autosummary::
+          :nosignatures:
+
+          getDisplayBounds
+          getDataResolution
+          destroy
+          preDraw
+          draw
+          postDraw
+
+    Alternately, a sub-class could derive from one of the following classes,
+    instead of deriving directly from the ``GLObject` class:
+
+    .. autosummary::
+       :nosignatures:
+
+       GLSimpleObject
+       GLImageObject
     """
 
     
@@ -130,11 +175,30 @@ class GLObject(object):
 
 
     def getDisplayBounds(self):
+        """This method must calculate and return a bounding box, in the
+        display coordinate system, which contains the entire ``GLObject``.
+        The bounds must be returned as a tuple with the following structure::
+
+            ((xlo, ylo, zlo), (xhi, yhi, zhi))
+        
+        This method must be implemented by sub-classes. 
+        """
+
         raise NotImplementedError('The getDisplayBounds method must be '
                                   'implemented by GLObject subclasses')
 
 
     def getDataResolution(self, xax, yax):
+        """This method must calculate and return a sequence of three values,
+        which defines a suitable pixel resolution, along the display coordinate
+        system ``(x, y, z)`` axes, for rendering this ``GLObject`` to screen.
+
+        This method should be implemented by sub-classes. If not implemented, a
+        default resolution is used.
+
+        :arg xax: Axis to be used as the horizontal screen axis.
+        :arg yax: Axis to be used as the vertical screen axis.
+        """
         return None
 
     
@@ -143,8 +207,9 @@ class GLObject(object):
         :class:`GLObject` changes. It sets :attr:`xax`, :attr:`yax`,
         and :attr:`zax` attributes on this ``GLObject`` instance.
 
-        Subclass implementations should call this method, or should set
-        the ``xax``, ``yax``, and ``zax`` attributes themselves.
+        Sub-classes may override this method, but should still call this
+        implementation, or should set the ``xax``, ``yax``, and ``zax``
+        attributes themselves.
         """
         self.xax = xax
         self.yax = yax
@@ -156,7 +221,7 @@ class GLObject(object):
         needed.
         
         It should perform any necessary cleaning up, such as deleting texture
-        handles.
+        objects.
         """
         raise NotImplementedError()
 
@@ -172,8 +237,8 @@ class GLObject(object):
 
     
     def draw(self, zpos, xform=None):
-        """This method should draw a view of this :class:`GLObject` at the
-        given Z position, which specifies the position along the screen
+        """This method should draw a view of this ``GLObject`` at the
+        given Z location, which specifies the position along the screen
         depth axis.
 
         If the ``xform`` parameter is provided, it should be applied to the
@@ -214,7 +279,8 @@ class GLSimpleObject(GLObject):
     """The ``GLSimpleObject`` class is a convenience superclass for simple
     rendering tasks (probably fixed-function) which require no setup or
     initialisation/management of GL memory or state. All subclasses need to
-    do is implement the :meth:`GLObject.draw` method.
+    do is implement the :meth:`GLObject.draw` method. The :mod:`.annotations`
+    module uses the ``GLSimpleObject`` class.
 
     Subclasses should not assume that any of the other methods will ever
     be called.
@@ -237,11 +303,12 @@ class GLImageObject(GLObject):
         """Create a ``GLImageObject``.
 
         This constructor adds the following attributes to this instance:
-        
-          - ``image``:       A reference to the image.
-          - ``display``:     A reference to the display.
-          - ``displayOpts``: A reference to the image type-specific display
-                             options.
+
+        =============== =======================================================
+        ``image``       A reference to the image.
+        ``display``     A reference to the display.
+        ``displayOpts`` A reference to the image type-specific display options.
+        =============== =======================================================
 
         :arg image:   The :class:`.Image` instance
         
@@ -259,10 +326,14 @@ class GLImageObject(GLObject):
 
         
     def __imageDataChanged(self, *a):
+        """Called when the :attr:`.Image.data` changes. Calls
+        :meth:`GLObject.onUpdate`. 
+        """
         self.onUpdate()
 
         
     def __del__(self):
+        """Prints a log message."""
         log.memory('{}.del ({})'.format(type(self).__name__, id(self)))
         
 
@@ -278,11 +349,17 @@ class GLImageObject(GLObject):
 
 
     def getDisplayBounds(self):
+        """Returns the bounds of the :class:`.Image` (see the
+        :meth:`.DisplayOpts.bounds` property).
+        """
         return (self.displayOpts.bounds.getLo(),
                 self.displayOpts.bounds.getHi())
 
 
     def getDataResolution(self, xax, yax):
+        """Returns a suitable screen resolution for rendering this
+        ``GLImageObject``.
+        """
 
         image   = self.image
         opts    = self.displayOpts
@@ -303,8 +380,9 @@ class GLImageObject(GLObject):
 
         
     def generateVertices(self, zpos, xform):
-        """Generates vertex coordinates for a 2D slice through the given
-        ``zpos``, with the optional ``xform`` applied to the coordinates.
+        """Generates vertex coordinates for a 2D slice of the :class:`.Image`,
+        through the given ``zpos``, with the optional ``xform`` applied to the
+        coordinates.
         
         This method is called by the :mod:`.gl14.glvolume_funcs` and
         :mod:`.gl21.glvolume_funcs` modules.